# Question
Title: How to use a Controller method inside a service with dependency injection?
I'm using the diff module for a project, this module has a method inside a Controller that I want to use in a service to reuse code. As this time I'm just calling the method like `PluginRevisionController::getRevisionIds()` but this give me the message:

> Deprecated function: Non-static method Drupal\diff\Controller\PluginRevisionController::getRevisionIds() should not be called statically

So, I want to 'inject' if possible in some way the Controller (I really don't know if this is possible) inside the service to reuse the logic. There is a way to do this?

# Answer
> 6 votes
You could inject a `ClassResolverInterface` or `ControllerResolverInterface` into your service to load a controller instance.

From core.services.yml:

```
controller_resolver:
  class: Drupal\Core\Controller\ControllerResolver
  arguments: ['@psr7.http_message_factory', '@class_resolver']
class_resolver:
  class: Drupal\Core\DependencyInjection\ClassResolver
  calls:
    - [setContainer, ['@service_container']]

```

Both classes will return an instance, just the method names differ.

```
$controller = $this->classResolver->getInstanceFromDefinition(PluginRevisionController::class);
$controller = $this->controllerResolver->getControllerFromDefinition(PluginRevisionController::class);

```

---
Tags: 8, dependency-injection, symfony-services
---


# Question
Title: How can I get a rendered node field value with filters applied?
I'm trying to use a REST resource that accepts a node title and returns a JSON interpretation of a single field. This requires raw HTML that I can then use in DOMDocument. To get the rendered value of a node programmatically with filters applied I tried:

```
$field_value = $node->get('body')->getValue();

```

However this doesn't apply any of the filters such as converting newlines/carriage returns into `<br/>` or striping out unwanted HTML tags. I don't intend to send this to a Twig template so I need the rendered value in a string rather than a render array.

How can I do that?

# Answer
> 2 votes
When you use Drupal in a site-building capacity, you use the Manage Display to configure field/layout configuration. What you're actually doing is choosing and configuring plugins to do the formatting for you, information that Drupal then uses to render an entity.

But when you're manually rendering entities or fields of entities, *all this work you have to do yourself*. When you do `->getValue()` or `->value`, what you're doing is extracting the raw value from the field, usually a programmatic representation of the value that's stored in the database. Entities also do not carry formatting on their own, that's information stored separate from the entity (e.g. display configuration) - a good example of separation of concerns, entity data vs entity display information.

You have choices though:

# Answer
> 2 votes
Thanks to everyone who helped out. In the end this is what I did to get the field to render with the filters applied.

```
/** @var \Drupal\node\NodeViewBuilder */
$view_builder = $this->entityTypeManager->getViewBuilder('node');

$field_render_array = $view_builder->viewField($node->get('body'), 'full');
// Deprecated switch to render service.
$html = render($field_render_array);

```

---
Tags: nodes, 9
---


# Question
Title: Adding placeholders to the user login block's username and password input fields
**Task**

I'm trying to add the placeholder attribute to the username and password input fields of the user login block.

**Problem**

When I have twig debug on, the only twig file overrides list are the following.

```
<!-- FILE NAME SUGGESTIONS:
* input--textfield.html.twig
x input.html.twig
-->

```

I don't want to use either of these twig files as it would apply to every input or every textfield.

**Caveat**

I'm wanting to accomplish this from within my theme not a custom module. Which I'm not sure is able to be done.

# Answer
> 3 votes
In twig it's difficult to target a specific input field. You can do this more efficient in a form alter hook, which you can use in themes too:

**mytheme.theme**

```
function mytheme_form_user_login_form_alter(&$form, $form_state) {
  $form['name']['#placeholder'] = t('placeholder for username');
}

```

# Answer
> 1 votes
```
/**
 * Implements hook_form_alter().
 */
function mytheme_form_alter(&$form, $form_state, $form_id) {
  if ($form_id == 'user_login_form' ) {
    // Add placeholders.
    $form['name']['#attributes']['placeholder'] = t('Email/Mobile Number');
    $form['pass']['#attributes']['placeholder'] = t('Password');
  }
}

```

# Answer
> 0 votes
clean solution

```
/**
 * Implements hook_preprocess_html().
 */
function THEME_preprocess_html(&$variables) {
  $current_path = \Drupal::service('path.current')->getPath();
  $path_alias = \Drupal::service('path.alias_manager')->getAliasByPath($current_path);
  $path_alias = ltrim($path_alias, '/');
  $variables['attributes']['class'][] = 'path-' . \Drupal\Component\Utility\Html::cleanCssIdentifier($path_alias);
}

```

---
Tags: theming, 8
---


# Question
Title: How can I avoid double line breaks (

) in a text field (field type: text unformatted long)?
How can I avoid double line breaks (`<br><br>`) in a text field (field type: text unformatted, long)?

Users write text into this text field. When they hit Enter twice, the result is: `<br><br>`. But `<br><br>` is not themable with css, the height of `<br>` can NOT be set with css.

Therefore `<br><br>` should be avoided and paragraphs `<p>` used instead of it. `<br><br>` should never be saved to database. How can double `<br><br>` be avoided or replaced with `<p>` before the the field is saved?

# Answer
> -1 votes
You can style br tag in CSS, but before you need to reset it by using these declarations:

```
br {
  display: "block";
  content: "";
}

```

Then you can style it as you want, it can be done using margin property, so the code will be such as:

```
br {
  display: "block";
  content: "";
  margin: 1em 0;
}

```

---
Tags: entities
---


# Question
Title: Storing PDF Subject Data in Media Entities
I have pdf documents that I need to create as entities on our website. The pdfs were created with metadata, such as title and subject, that we want to have available in Drupal.

I am trying to save the subject metadata in a new field that I added to the Document media type.

I do not believe that pdf metadata is being stored in either the media object or the file object by default.

I have attempted to hook into the media\_creation to save the field by using `hook_media_insert()` but I have not found an easy way to get that information yet either from the Media or File objects.

Is there a way to grab that metadata information from the pdfs?

# Answer
> 1 votes
Here is how I was able to achieve what I was looking for. The possible duplicate contained a piece of what I needed; however, the full implementation below addresses a few additional challenges.

```
use Drupal\file\Entity\File;

function my_module_media_presave(Drupal\Core\Entity\EntityInterface $media) {
  $fid = $media->get($media_field)->target_id;

  if(empty($fid)) {
    return;
  }
  $file = File::load($fid);

  // I set a limit of 3000 in order to mitigate out of memory errors for large PDFS
  $file_contents = file_get_contents($file->getFileUri(), false, null, 0, 3000);
  preg_match('/(?<=Subject)\S(?:(?<=\().+?(?=\))|(?<=\[).+?(?=\]))./', $file_contents, $subject);

  if(!empty($subject)) {
    $media->set('field_description', $subject[0]);
}

```

Note that this will keep the `()` around the description. If you don't want those then you can update the regex to do that or parse them out with a string replace.

---
Tags: media, files
---


title: download file on form submission

text:
# Question
Title: download file on form submission
I have created a form which has only a submit button. In the submit function I am generating csv file and saving it to the files folder using `fputcsv` function.

But Now I need extra functionality of submit. After saving the file it should download the file also.

How to do this? Any one have some idea about this?

# Answer
> 2 votes
Attach a form submit handler (code here: Drupal 7 custom form submit handler is not being called).

Then set the file url to $form\_state\['redirect'\].

The file download should begin when submitted.

# Answer
> 3 votes
In Drupal 8 to have the file download rather than redirect to it you can use:

```
$uri = $file->getFileUri();
  $headers = array(
    'Content-Type'     => $file->getMimeType(),
    'Content-Disposition' => 'attachment;filename="'.$file->getFilename().'"'
  );
  $form_state->setResponse(new \Symfony\Component\HttpFoundation\BinaryFileResponse($uri, 200, $headers, true));

```

# Answer
> 1 votes
In the following code I am downloading file as attachment created with phpExcel. It may help someone.

```
function dn_preorder_form_submit($form,&$form_state){
                $excel = new PHPExcel();
                $excel->setActiveSheetIndex(0);
                $excel->getActiveSheet()->setCellValue('A1',"TEST");

                header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
                header('Content-Disposition: attachment; filename="var.xlsx"');
                header("Pragma: no-cache");
                header("Cache-Control: no-cache");
                header("Cache-Control: nmax-age=0");

                $file = PHPExcel_IOFactory::createWriter($excel,'Excel2007');

                $file->save('php://output');
                exit();
    }

```

# Answer
> 0 votes
Assuming you are using a file stream, and Drupal specific

```
$filename = "report.csv";
$stream = "public://";
$uri = $stream . $filename; // Better to add a subfolder per context

$headers = [
  'Content-Type' => 'text/csv',
  'Content-Description' => 'File Download',
  'Content-Disposition' => 'attachment; filename="' . $filename . '"'
];

$rfh = fopen($uri, 'w');

fputcsv($rfh, ['ID', 'Mail', 'Name']);
fputcsv($rfh, ['1', 'xyz@do-re-mi.com', 'Jaffe Joffer']);

fclose($rfh);

$form_state->setResponse(new \Symfony\Component\HttpFoundation\BinaryFileResponse($uri, 200, $headers, true));

```

---
Tags: 7, forms
---


# Question
Title: Can we export json schemas for type script usage?
We have a Drupal installation that acts as a backend and a front end that uses the `HttpClientModule` from Angular to query this data.

Thanks to the typescript base, we can provide the functions of this service with the expected return type like `this.httpClient.get<ExpectedTypeInterface>(urlToJsonResource)`. The important question is: Where does the implementation of the `ExpectedTypeInterface` come from?

Wehn I inspect our API via OpenAPI/Swagger UI, I see that there is schema information available. Is there a standard way of exporting this information into typescript interfaces?

Creating them by hand would be a bad choice, because than the front end might get outdated type definitions.

# Answer
OpenAPI offers an endpoint under `/openapi/rest?_format=json` that delivers the complete json schema. For the transformation, we need the node package `json-schema-to-typescript`. This package offers a cli that lets us transform the json schema into a typescript file.
> -2 votes

---
Tags: entities, javascript
---


# Question
Title: How to change a field type from free-form text to a taxonomy term and keep its existing data?
I need to change one of the fields of a type of a node from a free-form text to be a taxonomy term, but the data already has about 250,000 records.

How can I change this field type without losing the existing data?

# Answer
> 4 votes
Changing the field type as you asked is not possible.

However a possible alternative to achieve a similar result is like so (in the order specified):

* Create a new taxonomy term field, so that "from now on" any future node updates (or new nodes being created) will use that new field.
* Use the Rules module to create a rule like so:
    + Rules event: `before saving content`.
    + Rules conditions:
        - `entity has field`, with field = the old field.
        - AND NOT (`entity has field`, with field = the new field).
    + Rules Action: `set Drupal message`, which contains some instructions that the old field must be blanked out, and the new field should contain the appropriate value(s.

Obviously, this approach will take "some" time if this has to be done manually, 1 node at a time. But using Views (to build a list of similar nodes to be updated) and VBO (to mass update such lists) you might (should!) be able to speed up this process quite a bit. Refer to my answer to "How to bulk update select list fields?" for an example with way more details about that.

# Answer
> 0 votes
For Drupal 8 and on Druidfire is, in general, a module written to directly manipulate field tables in the default SQL storage and their corresponding config. The functionality requested here just has been added.

---
Tags: 7, nodes, entities, taxonomy-terms
---


title: How do I change a field type?

text:
# Question
Title: How do I change a field type?
I have a content type with a *field\_maps* whose type is *Text (plain, long)*. I needed to change it to *Text (plain)*.

So I've done this SQL statement:

```
ALTER TABLE node__field_maps MODIFY field_maps_value VARCHAR(200);

```

It seems that *field\_type* has changed to `VARCHAR(200)`, but there is still one more problem: On the content type and manage fields tabs, the field is still shown as *Text (plain, long)*.

How do I change it to *Text (plain)*?

# Answer
I have also get this kind of issue that change field type from one to another with existing data. So as @Eyal mentioned, we can write an update hook to

1. export data from a field table to a variable
2. remove fields of all bundles
3. add new fields of all bundles
4. restore data to field table

Here is the code example

```
use \Drupal\field\Entity\FieldStorageConfig;
use \Drupal\field\Entity\FieldConfig;

/**
 * Change node__field_maps from string_long to string type.
 */
function mymodule_update_8XXX() {
  $database = \Drupal::database();
  $table = 'node__field_maps';
  $entity_type = 'node';
  $field_name = 'field_maps';

  $field_storage = FieldStorageConfig::loadByName($entity_type, $field_name);

  if (is_null($field_storage)) {
    return;
  }

  $rows = NULL;

  if ($database->schema()->tableExists($table)) {
    // The table data to restore after the update is completed.
    $rows = $database->select($table, 'n')
      ->fields('n')
      ->execute()
      ->fetchAll();
  }

  $new_fields = array();

  // Use existing field config for new field.
  foreach ($field_storage->getBundles() as $bundle => $label) {
    $field = FieldConfig::loadByName($entity_type, $bundle, $field_name);
    $new_field = $field->toArray();
    $new_field['field_type'] = 'string';
    $new_field['settings'] = array();

    $new_fields[] = $new_field;
  }

  // Deleting field storage which will also delete bundles(fields).
  $new_field_storage = $field_storage->toArray();
  $new_field_storage['type'] = 'string';
  $new_field_storage['settings'] = array(
    'max_length' => 255,
    'is_ascii' => FALSE,
    'case_sensitive' => FALSE,
  );

  $field_storage->delete();

  // Purge field data now to allow new field and field_storage with same name
  // to be created. You may need to increase batch size.
  field_purge_batch(10);

  // Create new field storage.
  $new_field_storage = FieldStorageConfig::create($new_field_storage);
  $new_field_storage->save();

  // Create new fields.
  foreach ($new_fields as $new_field) {
    $new_field = FieldConfig::create($new_field);
    $new_field->save();
  }

  // Restore existing data in the same table.
  if (!is_null($rows)) {
    foreach ($rows as $row) {
      $database->insert($table)
        ->fields((array) $row)
        ->execute();
    }
  }

}

```

**NOTE:** Always backup DB and test code before running this code

**Other thoughts** In my case, we also have exported configures which means the field type and settings are also included in field\_storage\_config, field\_config, entity\_form\_display, and entity\_view\_display config files. So we have to update config settings in those files as well. One easy way could be:

* clone your website
* delete the field and add a field with the same name again in field UI
* export configures to use them in the repo
* make sure the config uuid for the field and storage were not changed (change the uuid back if it was) to avoid the import potentially removing data.
* import configure after DB update and clear cache again

This is code is inspired by @drugan in the post https://www.drupal.org/node/2816859
> 21 votes

# Answer
I was facing a similar issue. After running the update\_hook described I was still facing a message about "Mismatched entity and/or field definitions" on status overview page. I think it was due to drush entup being removed in Drupal 8.7 I was able to solve this by manually forcing an update of FieldStorageDefinition like this:

```
function my_module_update_8002() {
  $entity_definition_update_manager = \Drupal::entityDefinitionUpdateManager();
  $entity_type = '[my_entity_type]';
  $field_name = '[my_field_name]';
  $field_storage = FieldStorageConfig::loadByName($entity_type, $field_name);
  $entity_definition_update_manager->updateFieldStorageDefinition($field_storage);
}

```
> 0 votes

# Answer
Druidfire is your friend. It's pure magic as the name suggests: it's a mini framework to manipulate entity data stored in the default SQL storage and the relevant configuration as well, bypassing most APIs. This particular conversion is not implemented yet but it wouldn't take more than ten minutes to add it, it's really easy. It already does string to formatted text for example with the `string2formatted*` methods, use these as a template for the change you want to implement.
> 0 votes

# Answer
This is the most optimal solution i found. This snippet works fine in drupal 8.9 and 9.1.

```
/**
 * Implements hook_update_N().
 */
function CUSTOM_MODULE_update_8001() {

  $entity_type_manager = \Drupal::entityTypeManager();
  $entity_type_manager->clearCachedDefinitions();
  $entity_type = $entity_type_manager->getDefinition('custom_entity');
  \Drupal::entityDefinitionUpdateManager()->installEntityType($entity_type);

  drupal_flush_all_caches();

  return t('Installed the CUSTOM ENTITY entity type');
}

```
> -1 votes

---
Tags: entities, 8, database
---


# Question
Title: Custom module name conflicts with unsupported contrib module -- how to avoid "This project is no longer supported" warning?
This Drupal 9 site runs a fork of the search\_file\_attachments module, modified for custom purposes, and for Drupal 9 compatibility.

For some time now, the Available updates report has shown, for this module, the warning "Project not supported: This project is no longer supported, and is no longer available for download. Disabling everything included by this project is strongly recommended!"

I intend to keep running this module as I might any other custom module, and would like Drupal to stop warning about this, on the rationale that this is no longer a contributed module in need of update status monitoring.

I've tried removing the d.o packaging info:

```
diff --git a/search_api_attachments.info.yml b/search_api_attachments.info.yml
index 2b2d3cf..adec8e7 100644
--- a/search_api_attachments.info.yml
+++ b/search_api_attachments.info.yml
@@ -3,12 +3,7 @@ name: 'Search API Attachments - Custom Fork'
 description: 'Extract and index file fields content.'
 core: 8.x
 core_version_requirement: ^8 || ^9
-package: Search
 configure: search_api_attachments.admin_form
 dependencies:
   - search_api:search_api

-# Information added by Drupal.org packaging script on 2020-04-04
-version: '8.x-1.0-beta16-custom-1'
-project: 'search_api_attachments'
-datestamp: 1586010934

```

I've also tried removing the composer.json file.

Both of these were followed by `drush cr` and then manually checking for updates with the "Check manually" link on the Available updates report, but the warning persists.

**Question:** Other than renaming the module (which I assume would solve the problem but is work I'd like to avoid), can I somehow instruct Drupal to stop checking for updates on this module?

# Answer
> 3 votes
The updates are checked via the core `update` module. The `update.manager` service allows a way to alter the list of projects it checks the data from via `hook_update_projects_alter`. Technically the following should work:

```
function MODULENAME_update_projects_alter(&$projects) {
  // Hide the forked module from the list.
  unset($projects['search_api_attachments']);
}

```

Please make sure you replace the MODULENAME with the actual module name where you are implementing this hook.

---
Tags: 9, .info
---


# Question
Title: How to display a user’s published content on their account?
Does anyone know how to display every article (or content type) a user has published on their "my account" view? To clarify, I only want it to display that specific user's published content so that all users can click on a user and then see all of that particular user's published content.

What I currently have set up so far is my account/user's view page setup and displays the user's username and ALL published content. Still, it isn't filtered by the specific user's account/ content, only if the content is published or not.

I've tried adding different filters, but none have worked for me. I've also tried adding a "username of the content author" relationship, but that still won't do the trick. If it's helpful, the view's URL is /user/\* (\* representing a different number depending on which user's account view you are on)

Update: I installed pathauto module and changed the view's URLs to /user/\[username\] (so if your username is "human," the URL is now /user/human)

# Answer
> 1 votes
You are creating a view. Since you want it on the entity.user.canonical route, you need to create a block.

The view needs a contextual filter to use the user id from the URL path as a filter.

Next to **Contextual filters** click Add. Select 'Content: Authored By'. In **When the filter is NOT in the URL** select 'Provide default value'. Set Type to 'User Id from route context'

add a contextual filter to a view

---
Tags: views, users, 9
---


# Question
Title: Passing preprocess function variables to a template
I am trying to include another template file with pre-process's theme hook variables in a template file but it failed. I checked theme debug and it does not include example's pre-process theme hook. Can you give me guidance?

I added `{% include 'example--p1.html.twig' %}` in the page--front.html.twig file. The example--p1.html.twig file has one variable, `{{ test }}`. Also, I created a pre-process function that adds variables to a page template. The code is the following.

```
function mytheme_preprocess_example__p1(array &$variables, $hook) {
  $variables['test'] = 'please help';
  $variables['test_var'] = 'this is my second variable';
}

```

It doesn't appear in the example--p1.html.twig template.

Someone suggested using the following code in the page--front.html.twig file.

```
{% include 'example--p1.html.twig' with {'test' : 'this is my message'} %}

```

I then added the following code in the following files.

### mytheme.theme

```
function mytheme_preprocess_example__p1(array &$variables, $hook) {
  $variables['content']['text'] = 'second';
}

```

### page--front.html.twig

```
{% include 'example--p1.html.twig' with {'test' : 'content.text'} %}

```

It works as it shows the text message value in example--p1.html.twig and page--front.html.twig.

How can I pass pre-process function's text messages' variables to page example--p1.html.twig and then I can display all the variables if I include example--p1.html.twig to page--front.html.twig?

# Answer
> 3 votes
Preprocess functions are part of a render setup that includes at least:

* `hook_theme()` to register the template to Drupal.
* `hook_preprocess_HOOK` to preprocess template variables before it's handed to Twig.
* The twig template to represent the HTML of the template.
* Something that "builds" the interface using the above setup.
    + This involves creating a render array with `#type` set to the registered template's name to render the data using the template. Examples of this are field formatters, controllers, blocks, etc.

The general flow of a render is `build -> preprocess -> twig = HTML`

Essentially a long-winded way of saying *not all twig templates have preprocess functions*. Twig templates that are just "included" are not part of this mechanism and won't have preprocess function.

# Answer
> 3 votes
For your front page twig: page--front.html.twig -- you would want to add a variable in the THEMENAME\_preprocess\_page function.

Preprocess functions would essentially match what the twig is targeting -- page data. If your twig was for a node, then you'd want a preprocess\_node.

```
function THEMENAME_preprocess_page(array &$variables, $hook) {
  if (\Drupal::service('path.matcher')->isFrontPage()) {
    $variables['some_variable'] = 'some value';
  } else {
    $variables['some_variable'] = 'a different value';
  }
}

```

And then I think your include just needs to do this

```
{% include 'example--p1.html.twig' with {'test' : some_variable } %}

```

---
Tags: 9
---


# Question
Title: Programmatically add new fields to content type
I have a custom module that has a form that allows the user to select various content types. I would like to create fields for those content types programmatically so that after the form is saved, it will add the fields for all of the content types that the user selected.

So my question is, is there a way to programmatically create fields and then save them to the content types? Any direction (tutorials, etc) would be greatly appreciated. I've searched for a while, but most of what I'm seeing is for d7 which obviously isn't what I'm looking for since this is for d9.

# Answer
For the PHP commands necessary to programmatically add new fields to content types see:

Add content type field programmatically

*That reference adds a body field when the content type is created.* When you want to add fields to existing content types then load them in a loop:

```
foreach (NodeType::loadMultiple() as $type) { }

```

*How would I even translate that to a date field (for instance)?* To get the necessary plugin names and settings add the field in UI temporarily. Export the configuration and compare it with the previous configuration. You find two new YAML files, the field storage (in UI the field settings) and the bundle field definition (in UI the field edit). The display and form settings are added to existing YAML files. Make a diff to find the new entries. With this information you can fill the parameter lists of the PHP methods and, if you want, you can use the YAML file of the field storage like described in the linked answer.
> 0 votes

# Answer
How necessary is the part of it being programmed by yourself? It sounds like having a large overlap with the Entity Construction Kit. Probably, things might work with less own code than you expect.

If your use case is really that special, I still recommend you this module as reading material. It might contain the snippets that you need.
> -1 votes

---
Tags: 9, configuration
---


# Question
Title: Add js library to custom ckeditor4 plugin
**How can an external JS library be integrated into Drupal for use within a custom Ckeditor4 plugin?**

My custom plugin needs to set a javascript cookie each time I click on the plugin icon and unset when I close the plugin dialog.

I attempted to use JQuery which didn't work and when I googled the issue, I found a post saying the jquery-cookie is being replaced with js-cookie.

I attempted to install js-cookie and tried the following example:

```
(function ($, Drupal, drupalSettings, CKEDITOR, Cookies) {
    Cookies.set('foo', 'bar')
})(jQuery, Drupal, drupalSettings, CKEDITOR, window.Cookies);

```

but got the following error:

> Uncaught TypeError: Cannot read properties of undefined (reading 'set')

*I'm not sure if it's becuase of the way I attached the JS-Cookie library.*

**The following are the steps I took to attach the library.**

I used a composer plugin to require js-cookie into my custom module. My composer.json is as follows:

```
{
    "name": "my/module",
    "description": "Custom module ckeditor4 plugin",
    "authors": [
        {
            "name": "my-name",
            "email": "my@email.com"
        }
    ],
    "repositories": [
        {
            "type": "composer",
            "url": "https://asset-packagist.org"
        }
    ],
    "extra": {
        "installer-types": [
            "npm-asset",
            "bower-asset"
        ],
        "installer-paths": {
            "libraries/asset-packagist/{$name}": [
                "type:npm-asset",
                "type:bower-asset"
            ]
        }
    },
    "require": {
        "oomphinc/composer-installers-extender": "^2.0",
        "npm-asset/js-cookie": "^3.0",
        "npm-asset/cookie": "^0.5.0"
    }
}

```

Which downloads the required library into the following directory structure from the root of the module code base:

```
libraries
├── asset-packagist
│   ├── cookie
│   └── js-cookie

```

At this point I am able to create an entry in my\_module.libraries.yml using the following:

```
js-cookie:
  js:
    libraries/asset-packagist/js-cookie/dist/js.cookie.min.mjs: {}
  dependencies:
    - core/jquery
    - core/drupalSettings

```

. . . and attach the library to a form using the following hook\_form\_alter implementation:

```
function my_module_form_alter(&$form, &$form_state, $form_id) {
  $form['#attached']['library'][] = 'my_module/js-cookie';
}

```

And I confirmed the js-cookie library is sucessfully loaded in the HTML:

# Answer
I think you should delete these lines from your library file.

```
js-cookie:
  js:
    libraries/asset-packagist/js-cookie/dist/js.cookie.min.mjs: {}
  dependencies:
    - core/jquery
    - core/drupalSettings

```

You try need to replace the used library **core/jquery.cookie** to **core/js-cookie**.

my\_module.libraries.yml

```
my_library:
  js:
    js/my_library.js: {}
  dependencies:
    - core/drupal
    - core/js-cookie
    - core/drupalSettings
    - core/jquery

```

js/my\_library.es6.js

```
(($, Drupal, drupalSettings, CKEDITOR, cookies) => {
  Drupal.behaviors.myModule = {
    attach: () => {
      // Set a cookie.
      cookies.set('cutest', 'red panda');
      // Retrieve a cookie.
      const cutest = cookies.get('cutest');
      // Remove a cookie.
      cookies.remove('cutest');
      // Store and retrieve as a JSON object. Use of the getJSON method should be avoided as that will be deprecated in js-cookie 3.0.0.
      cookies.set('cutest', JSON.stringify({ animal: 'red panda' }));
      const cutest = JSON.parse(cookies.get('cutest'));
    },
  };
})(jQuery,Drupal, drupalSettings, CKEDITOR,window.Cookies));

```

Here is the official documentation with an anchor to the part that explain how to use js-cookie: https://www.drupal.org/node/3104677
> 0 votes

---
Tags: javascript, 9, wysiwyg
---


title: Custom event from existing event

text:
# Question
Title: Custom event from existing event
I've been reading for days, trying several examples but I'm just not getting it.

I have the Rules module as well as the H5P module. I'm attempting to create a Rules event from the existing H5PFinished event (which may or may not be the way to go about this).

Their function constructs an array of five fields, which then update in the GDB.

```
// which fields to update
$fields = [
  'content_id' => $content_id,
  'uid' => $uid,
  'finished' => time(),
  'points' => $score,
  'max_points' => $max_score,
];

```

They then invoke an event.

```
$this->eventDispatcher->dispatch(FinishedEvent::FINISHED_EVENT, new FinishedEvent($fields));

```

In the FinishedEvent.php file, they name the event and return the fields as an array.

```
class FinishedEvent extends Event {

  const FINISHED_EVENT = 'h5p.finished';

  /**
   * @var array
   */
  protected $quizData;

  /**
   * Constructs a FinishedEvent object.
   *
   * @param array $quiz_data
   *   Database connection service.
   */
  public function __construct(array $quiz_data) {
    $this->quizData = $quiz_data;
  }

  /**
   * @return array
   *   Quiz data.
   */
  public function getQuizFields() {
    return $this->quizData;
  }

}

```

I'd like to be able to have a custom rule event which basically is fired when the database is updated, and if the user has score == max\_score, a data value is set in their user profile (I do have the actions working fine. I tested using a simple "if page is viewed). I'm just super lost.

I've created the custom module to add the Event to Rules. I've used the event name defined in and subscribed to in H5P ("h5p.finished") and added four integer type context\_definitions (which worked earlier, but now throws an error that the data needs to be of type array, string given).

### mymodule.rules.events.yml

```
h5p.finished:
label: 'Interactive Content is Solved'
category: 'H5P'
context_definitions:
   content_id:
      type:'integer'
      label:'Content ID'
   max_score:
      type:'integer'
      label:'Max Score'
   score:
      type:'integer'
      label:'Score'

```

# Answer
1. `type:'integer'` is not valid yaml, you must have a space after the colon, `type: 'integer'`
2. You didn't indent fields that are after the event machine name, `h5p.finished:`
3. Use the same keys as the `$fields` array.

```
h5p.finished:
  label: 'Interactive Content is Solved'
  category: 'H5P'
  context_definitions:
    content_id:
      type: 'integer'
      label: 'Content ID'
    max_points:
      type: 'integer'
      label: 'Max Score'
    points:
      type: 'integer'
      label: 'Score'

```
> 1 votes

---
Tags: rules, 9
---


# Question
Title: How to reset cache on a specific page by a given URL?
In Drupal 7, I found a way to reset cache on a specific page with:

```
$url = url('<front>',  array('absolute' => TRUE));
cache_clear_all($url, 'cache_page');

```

What is the equivalent way in Drupal 9?

# Answer
> 2 votes
Solved it like this:

```
$url = Url::fromUserInput($custom_url);
  if ($url instanceof UrlInterface) {
    if ($url->isRouted()) {
      $nid = $url->getRouteParameters()['node'];
      /** @var \Drupal\node\Entity\Node $node */
      $node = Node::load($nid);
      if ($node instanceof NodeInterface) {
        $tags = $node->getCacheTags();
        \Drupal::service('cache_tags.invalidator')->invalidateTags($tags);
      }
    }
  }

```

---
Tags: 9
---


title: Logged in user data, after logout

text:
# Question
Title: Logged in user data, after logout
I need the ID of the logged in user, after logging out. I tried to use a session variable, but all data is lost on exit. Is there any method to use, other than the query parameter?

```
┌──────────────┐                        ┌──────────────┐
│              │                        │              │
│  Page        │       ┌────────┐       │  Page        │
│              │       │        │       │              │
│  generation  │ ────► │ logout │ ────► │  generation  │
│              │       │        │       │              │
│  (UID: ?)    │       └────────┘       │  (UID: 0)    │
│              │                        │              │
└──────────────┘                        └──────────────┘

```

What is original user ID?

# Answer
`user_logout()` contains `\Drupal::service('session_manager')->destroy();` there is no chance of recovering the session after that. You need to set a cookie with the user id of the currently logged in user in `hook_user_logout`. Luckily the hook gets the `$user` as argument.
> 4 votes

---
Tags: users
---


# Question
Title: Drupal and reverse proxy: How to make Drupal aware that it's protocol is HTTPS?
I have a reverse proxy Docker container in front a Drupal container on a Docker host.

My reverse proxy container is https://hub.docker.com/r/jwilder/nginx-proxy

The public site URL is https://ahora-stage2.dcycleproject.org

When a request is made to https://ahora-stage2.dcycleproject.org, drupal receives the following headers. I ran `dpm(\Drupal::request()->headers);` using devel/php on a backend web interface:

```
stdClass Object ( [__CLASS__] => Symfony\Component\HttpFoundation\HeaderBag [headers:protected] => Array ( [authorization] => Array ( [0] => ) [host] => Array ( [0] => ahora-stage2.dcycleproject.org ) [connection] => Array ( [0] => close ) [x-real-ip] => Array ( [0] => 216.246.250.184 ) [x-forwarded-for] => Array ( [0] => 216.246.250.184 ) [x-forwarded-proto] => Array ( [0] => https ) [x-forwarded-ssl] => Array ( [0] => on ) [x-forwarded-port] => Array ( [0] => 443 ) [content-length] => Array ( [0] => 212 ) [accept] => Array ( [0] => text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 ) [content-type] => Array ( [0] => application/x-www-form-urlencoded ) [origin] => Array ( [0] => https://ahora-stage2.dcycleproject.org ) [accept-language] => Array ( [0] => en-ca                 ) [user-agent] => Array ( [0] => Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.3 Safari/605.1.15 ) [referer] => Array ( [0] => https://ahora-stage2.dcycleproject.org/devel/php ) [accept-encoding] => Array ( [0] => gzip, deflate, br ) [cookie] => Array ( [0] => SESS06c9cc57c2abbd62a4b35358c6967749=zmOe3Gexxxxxxxx7238990ldZb50rMxl35yPOeM ) [x-php-ob-level] => Array ( [0] => 0 ) ) [cacheControl:protected] => Array ( ) )

```

Based on that information, https://x-team.com/blog/base\_url-drupal-8/, https://medium.com/@lmakarov/drupal-8-and-reverse-proxies-the-base-url-drama-c5553cbc9a3e, and comments in the settings.php file, I put these custom settings in my Drupal settings.php file:

```
$settings['reverse_proxy'] = TRUE;
$settings['reverse_proxy_addresses'] = ['104.236.70.29','216.246.250.184'];

```

Nonetheless, Drupal always keep believing that the protol is HTTP, not HTTPS.

See enclosed image.

I'm wondering how I could set it up so that Drupal understands that it's behind a reverse proxy and that it's public URL should be served using the https protocol.

# Answer
> 1 votes
It turns out the IP which should be in the reverse\_proxy\_addresses is neither the IP which you get when you ping the domain, nor the ID in the headers which you can inspect. Rather, you need to temporarily install devel\_php on your site, and then go to /devel/php and enter dpm($\_SERVER\['REMOTE\_ADDR'\]);. This will give you a result such as 172.18.0.5, which then goes in $settings\['reverse\_proxy\_addresses'\];

More info at https://blog.dcycle.com/blog/170a6078/letsencrypt-drupal-docker/

# Answer
> 0 votes
I ran into a similar situation getting a complex site set up on DigitalOcean's App Platform: on the Drupal end, Drupal core and PHP info were seeing plain old HTTP and not HTTPS, likely due to how their services get set up - it's still HTTPS outside of your app container, but Drupal doesn't know this. It was causing various problems which led me down a rabbit hole of learning how to set up the reverse proxy stuff in Drupal core. I don't know if this solves your whole issue, but I found the Trusted Reverse Proxy module very helpful in automating parts of the configuration, namely setting the IPs that are to be trusted.

---
Tags: uri
---


# Question
Title: How can I have the file upload destination private by default?
Currently Webform file component uses public files as default upload destination. This is probably because private files path is not always available if not configured in Drupal settings correctly.

File upload destination should be made automatically "private files" by default if available.

I found same issue with Drupal7, is there any patch or way for Drupal8?

Or better if we do it by some setting in the local.settings.php or some similar cofniguraions?

https://www.drupal.org/forum/support/upgrading-drupal/2012-10-08/changing-public-file-field-into-private

# Answer
> 0 votes
With file\_save\_data being removed from Drupal 10, this is how I now save a file upload to my file field type. $docs is the array that my decoupled Formik form provides on form submit and I had to extract the data from the array and decode. I then get the file id to put into the file field on the node. Probably a better way, but I made this work.

```
/**
   * @param $docs
   * Save all doc attachments to the private directory.
   *
   * @throws \Drupal\Core\Entity\EntityStorageException
   */
  public function saveDocuments($docs): void {
    foreach ($docs as $key => $dataIn) {
      // Save the plate with the filename for audit trail.
      $this->fileName = $this->license . '-' . $dataIn['filename'];
      $data = $dataIn['file_data'];
      [$type, $data] = explode(';', $data);
      [, $data]      = explode(',', $data);
      $data = base64_decode($data);

      /** @var \Drupal\file\FileRepositoryInterface $fileRepository */
      $fileRepository = \Drupal::service('file.repository');
      $uri = "private://" . $this->fileName;
      $fileEntity = $fileRepository->writeData($data, $uri, FileSystemInterface::EXISTS_REPLACE);
      $this->documents[] = $fileEntity->id();

    }
  }

```

---
Tags: 8, files, webforms
---


# Question
Title: Reference View in Entity Reference field
I have a content type that has an entity reference field allowing you to link to other pages and add a custom image, for nice big CTAs.

However, it's come to light that some of the links may need to be to Views that show content as a list or map.

The ER field has autocomplete enabled and it can't find the view by its URL e.g /my-view

Is there a plugin that would allow the field to find Views? Or do I have to change the content type and add a Link field instead?

# Answer
> 0 votes
Views are config entities so you can target them to be referenced (see screenshots) and check this post.

The caveat is you can only point to a given entity type when using ER fields so you cannot have an ER field targeting content and config alike.

On the other hand almost any market solution referencing views aim to render it not just displaying a link pointing the view.

As you suggest using a link field can work around with your use case but the link form element only autocompletes content entities, you cannot type your views' display title and wait for it to get the proper URL for you. For that I'm afraid you need to provide your own widget/form element (and controller). Check this and this about how to build your own autocomplete widget/form element for a text field and this post from Drupal.org docs on how to build your own field formatter.

Also worth noticing that Views URL's are used on limited display types (Page, Feeds, possibly 2 more but I'm not quite sure) and is considered a route, not a path or link like when building a menu link item.

Hope this points you in the right direction.

# Answer
> 0 votes
As others have mentioned, the Views Reference Field module does this nicely (not to be confused with View Reference).

It defined a new field type for you to reference in Entity Reference Fields, allowing Editors to link to pre-build Views. It also helpfully allows defining exactly which views and display modes you want to expose via the UI:

And here is how it can look in the Node form:

# Answer
> -1 votes
One way to handle this is to make the view page into a block, then create a node with no content that contains this block (block placement in main content with limited view to /node/. Then use this in the entity reference field.

An alternative might be to have a content type that uses one of the views fields like view reference. Then just create a view node with the desired view and use it.

---
Tags: views, 8, entities
---


# Question
Title: How do I configure sites.php for a multi-site with fixed IP and subdir?
I have just installed clean minimal Drupal 9, created a `sites/sites.php` with the following line

```
$sites['10.0.0.133.drupal.web.foo-bar'] = 'foo-bar.com';

```

and the following subdir `sites/foo-bar.com` with `settings.php` that includes the correct database settings. After entering `http://10.0.0.133/drupal/web/foo-bar` into the browser, the `default` site respond which means the site alias has not been recognized.

Any idea? Do I need a web server vhost created for each site?

# Answer
After some trying I've found that there HAS to be a web server virtual host pointing at the root drupal directory
> 0 votes

---
Tags: multi-sites
---


# Question
Title: How can I dynamically change the default value for views exposed filter based on the terms weight?
I have an exposed filter in a view is referencing taxonomy terms from specific vocabulary. The operator allows selecting a term as the default value for that filter. What I want to achieve is to dynamically select the default value when the term weight = 0.

This should allow less privileged roles like Content Contributors to set the default value for the exposed filter by changing the order (weight) of the term without the need to edit the views settings.

I tried to research this and so far, it seems the best way to achieve this is by using (hook\_views\_pre\_build) but I just don't know how.

# Answer
After extensive search and experiment, this code worked for me:

```
use Drupal\taxonomy\Entity\Term;
use Drupal\views\ViewExecutable;

/**
 * Implements hook_views_pre_build().
 */

function YOUR_MODULE_NAME_views_pre_build(ViewExecutable $view) {
  if ($view->id() == 'YOUR_VIEW_ID' && $view->current_display == 'YOUR_DISPLAY_ID') {
    // Get the exposed filter for the taxonomy terms.
    $filter = $view->display_handler->getHandler('filter', 'YOUR_FILTER_ID');
    if ($filter) {
      // Query the database for taxonomy terms with a weight of 0.
      $query = \Drupal::entityQuery('taxonomy_term');
      $query->condition('weight', 0);
      $term_ids = $query->execute();
      if (!empty($term_ids)) {
        // Load the first term found with a weight of 0.
        $term = Term::load(array_shift($term_ids));
        if ($term) {
          // Set the default value for the exposed filter to the term's ID.
          $filter->options['value'] = $term->id();
        }
      }
    }
  }
}

```

This code will query the database for taxonomy terms with a weight of 0 when the specified view is pre-built and set the default value for the exposed filter to the ID of the first term it finds. If no terms are found with a weight of 0, it will not change the default value.
> 1 votes

---
Tags: views, hooks
---


# Question
Title: Avoid group of revisions history view duplication
My taxonomy View lists all revisions grouping by different columns, by adding revision fields for each value, and get the filter "published" removed. The only filter is: city name (not null).

For example:

| London | Roma |

| value 1 | value 1 |

| value 2 | value 2 |

As you can tell, people can add different city data by making new revision of the taxonomy. It works perfect, except one thing - If people want to revise an existed City, he will need to make a new revision, which will duplicate the city name on my View (resulting two columns of a same city).

Is there any way we can hide the elder column if city name duplicates? I just want to keep "London & Roma", not "London & Roma & London"

There is no luck with Views Distinct & Views Field Compare, those two modules won't help. Same with built-in Aggression.

Thanks. Drupal 8.9.

# Answer
> 1 votes
I changed the view to Grid layout, grouping by City, so that I can hide every views-col in each group except the last one, by css control:

```
.views-view-grid .views-row .views-col {
display:none;
}
.views-view-grid .views-row .views-col:last-child {
display:inline-block !important;
}

```

It works. But wondering if there is any other way.

---
Tags: views, taxonomy-terms
---


# Question
Title: How to render fields with ->view() in a render array table?
I am building a table in my build function of a block and want to render formatted field values or entities with the `->view();` method in a cell of my table.

As described here: https://www.computerminds.co.uk/articles/rendering-drupal-9-fields-right-way

I have a value like this:

```
$cell_value = $entity->field_name->view();

```

It outputs a render array. But when I put it in the table like this. Nothing shows up.

```
  $header = [
      'col1' => t('COL1'),
      'col2' => t('COL2'),
    ];
    $rows = [
      ['test col 1', $cell_value],
      ['test col 1', 'test'],
      ['test col 1', 'test'],
    ];
    return [
      '#type' => 'table',
      '#header' => $header,
      '#rows' => $rows,
    ];
  }

```

But when I render it like this:

```
return $cell_value;

```

I see a rendered value. Is there a way to render it in a table and how? Currently I am making every field manually which is very time consuming.

# Answer
> 2 votes
Usually it helps to put the render array in a `data` subkey:

```
$rows = [
  ['test col 1', ['data' => $cell_value]],
  ...

```

---
Tags: theming
---


# Question
Title: How to make Paragraph label configurable
Drupal version 8.4.4

I have a paragraph type defined (For example Links), which only has one field of type link.

And I have Entity reference revisions field in my node edit form.

When I view the node i see the referenced field Label, How to make this label configurable?

# Answer
> 0 votes
You have a few options:

* As commented, either make it a non-paragraph field
* Implement some custom form alter, change the the label there
* Use two different paragraph types with a different label, allow only one of the two on each node type.

# Answer
> 0 votes
You can extend the entity with a custom class and set it as the class to use for that entity type.

Extend the Paragraph entity class and override the `label()` method like this:

```
class ParagraphExt extends Paragraph {
  function label() {
    return "your label";
  }
}

```

Then set it as the class to use in `hook_entity_type_alter` like:

```
function hook_entity_type_alter(array &$entity_types) {
  $entity_types['paragraph']->setClass(ParagraphExt::class);
}

```

---
Tags: 8, entities, paragraphs
---


# Question
Title: CORS policy: No 'Access-Control-Allow-Origin'
I have two sites. On the first, I created a REST export page with information I need on the second one. I got this working for some years, but since my last update to Drupal 9.4.4 and from PHP 7 to PHP 8, it doesn't anymore.

The full error message is the following.

> Access to XMLHttpRequest at 'https://site1.com/json/site1-agenda?today=08042022&\_format=json' from origin 'https://site2.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

On the first site, I have the following CORS information in services.yml.

```
enabled: true
# Specify allowed headers, like 'x-allowed-header'.
allowedHeaders: ['*']
# Specify allowed request methods, specify ['*'] to allow all possible ones.
allowedMethods: ['GET']
# Configure requests allowed from specific origins.
allowedOrigins: ['https://site2.com']
# Sets the Access-Control-Expose-Headers header.
exposedHeaders: true
# Sets the Access-Control-Max-Age header.
maxAge: true
# Sets the Access-Control-Allow-Credentials header.
supportsCredentials: true

```

Is there anything wrong with my setup? Or a way to debug this?

# Answer
> 2 votes
Try this:

On my **site1.local** following info in `services.yml` file.

```
  cors.config:
    enabled: true
    # Specify allowed headers, like 'x-allowed-header'.
    allowedHeaders: ['x-csrf-token','authorization','content-type','accept','origin','x-requested-with']
    # Specify allowed request methods, specify ['*'] to allow all possible ones.
    allowedMethods: ['*']
    # Configure requests allowed from specific origins.
    allowedOrigins:  ['http://site2.local']
    # Sets the Access-Control-Expose-Headers header.
    exposedHeaders: false
    # Sets the Access-Control-Max-Age header.
    maxAge: 1000
    # Sets the Access-Control-Allow-Credentials header.
    supportsCredentials: true

```

and in my **site2.local**

`services.yml` file

```
  cors.config:
    enabled: true
    # Specify allowed headers, like 'x-allowed-header'.
    allowedHeaders: ['x-csrf-token','authorization','content-type','accept','origin','x-requested-with']
    # Specify allowed request methods, specify ['*'] to allow all possible ones.
    allowedMethods: ['*']
    # Configure requests allowed from specific origins.
    allowedOrigins:  ['http://site1.local']
    # Sets the Access-Control-Expose-Headers header.
    exposedHeaders: false
    # Sets the Access-Control-Max-Age header.
    maxAge: 1000
    # Sets the Access-Control-Allow-Credentials header.
    supportsCredentials: true

```

it works for me.

# Answer
> 1 votes
In services.yml, update exposedHeaders under cors.config to an array.

```
exposedHeaders: []

```

I had the same issue, and I found that it is related to PHP 8.1 and the 'asm89/stack-cors' dependency not being updated.

---
Tags: 9
---


# Question
Title: How do I change the "secure" and "httpOnly" attributes of the cookies provided by the EU Cookie Compliance module?
I am using the eu cookie compliance module in Drupal 9 and I need to change the "secure" and "httpOnly" values of the cookies, as I am getting a vulnerability error "CWE-614: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute". I have tested from the settings.php using the following code:

```
ini_set('session.cookie_secure', 1);

```

However it didn't work, I also tried with some modules but it didn't work either.

# Answer
> 1 votes
By looking over the 8.x-1.x branch of that module, what you are asking seems to be unsupported there. It sets cookies like:

```
cookies.set(cookieName, status, { path: path, domain: domain, sameSite: 'strict' });

```

However, `cookies.set` supports all the possible options.

So the answer to this question is: Open a feature request with the module maintainers, or patch the files in the `js` directory, or both.

---
Tags: 9, cookies
---


# Question
Title: How to change media image private to media image public, just for a specific filemime, and update the url?
Using Drupal 9.4. The Media File system is set to Private The Drupal default media type Image is set to private. It now contains hundreds of images. We want to switch only this media type from private to public. We want to keep PDF files private, these are in the Drupal default media type Document.

My process is this. Copy all the images from the private folder over to the public folder, keeping the original sub-directories. Then delete the images from the private folder. Go to \> Media Types \> Image \> Manage fields \> Edit image \> Field settings - Switch from private to public. Note\* It says. There is data for this field in the database. The field settings can no longer be changed. But it accepts the change to public.

Next, update the url in the file managed SQL table, so the url path is public instead of private. This command came from this post. And works great. It updates every file including pdf, word and jpegs. But I just want to update jpeg, png, gif. Can it be modified to only effect a certain filemime? I can run it 1 at a time for each filemime.

```
UPDATE file_managed SET uri = REPLACE(uri, 'private://', 'public://') where instr(uri, 'private') > 0;

```

In the SQL File Managed table there is a column filemime. The example data in this is: image/jpeg image/gif application/pdf Would it be something like this to target the filemime

```
WHERE filemime = 'image/jpeg';

```

# Answer
In general, you should avoid updating tables directly in favor of using Drupal's APIs, so I would not recommend using an SQL query like that.

I had to do the exact opposite of this recently - move files from public to private. The process is the same, here's what I did:

1. Update the file field's settings to point to the new destination, e.g. from private to public. This will ensure any future files go to the new spot. (You noted that you did this.)
2. Next, we need to update all existing files. To do this, I wrote a post\_update hook to move the files for all of the file entities. (This will be in lieu of the SQL query you're trying to use and you also won't need to manipulate the filesystem directly, i.e. no copying files to different directories, etc.) Note that I did use a batch process, but here's the heart of the code:

```
$new_file_dir = 'public://my-new-file-directory/';

$mimes = [
  'image/jpeg',
  // etc...
];

// Get the file entity ids for the files with your wanted file mimes.
$file_entity_ids = \Drupal::entityTypeManager()
  ->getStorage('file')
  ->getQuery()
  ->condition('filemime', $mimes, 'IN')
  ->execute();

// Load the file entities.
$file_entities = \Drupal::entityTypeManager()
  ->getStorage('file')
  ->loadMultiple($file_entity_ids);

// Move the files associated with the file entities.
foreach ($file_entities as $file) {
  \Drupal::service('file.repository')
    ->move($file, $new_file_dir . $file->getFilename());
}

```
> 2 votes

---
Tags: media, 9
---


# Question
Title: How to get each field value in views-views-unformatted--view-machine-name.html.twig?
I have an twig file: *views-view-unformatted--view-machine-name.html.twig*

```
{#
/**
 * @file
 * Default theme implementation to display a view of unformatted rows.
 *
 * Available variables:
 * - title: The title of this group of rows. May be empty.
 * - rows: A list of the view's row items.
 *   - attributes: The row's HTML attributes.
 *   - content: The row's content.
 * - view: The view object.
 * - default_row_class: A flag indicating whether default classes should be
 *   used on rows.
 *
 * @see template_preprocess_views_view_unformatted()
 *
 * @ingroup themeable
 */
#}
{% if title %}
  <h3>{{ title }}</h3>
{% endif %}
{% for row in rows %}
  {%
    set row_classes = [
      default_row_class ? 'views-row',
    ]
  %}
  <div{{ row.attributes.addClass(row_classes) }}>
    {{ row.content }}
  </div>
{% endfor %}

```

I want to have `Title` and `body` *field* to be in 1 line separated by comma like:

*title, body*

How can I get value of 'title' or 'body' or any other field in this view while debugging?

I used kint(title) and kint(body) but it's not working. I also made `debug = TRUE;` in services file.

But can't figure out the way of having fields value in unformatted html twig.

# Answer
> 27 votes
As you can see in views-view-unformatted.html.twig, it says what also the commented code you've shown says, there is no fields variable. Therefore, this template is not used for fields.

> Available variables:
>
> * title: The title of this group of rows. May be empty.
> * rows: A list of the view's row items.
>     + attributes: The row's HTML attributes.
>     + content: The row's content.
> * view: The view object.
> * default\_row\_class: A flag indicating whether default classes should be used on rows.

If you want to use fields in a view template, use **views-view-fields--\[view-name\]--\[machine-name\].html.twig**. There, you can print your fields like this:

```
<span>{{ fields.title.content }},</span><span>{{ fields.body.content }}</span>

```

# Answer
> 31 votes
**I have found a Way using Kint, You can get field values in views-view--unformatted.html.twig**

**if you want a specific field**

To get text fields value

`{{row.content['#row']._entity.field machine name[0].value}}`

To get image fields src

`{{file_url(row.content['#row']._entity.field machine name.entity.uri.value)}}`

To get image alt,title,width,height

`{{row.content['#row']._entity.field machine name[0].alt/title/width/height}}`

> Note : replace field machine name with your fields machine name

**If you Want to loop through multiple field**

```
{% for i in range(0, 10) %}
  {{ row.content['#row']._entity.body[i].value }}
{% endfor %}

```

**If you Want raw value**

```
{% for i in range(0, 10) %}
  {{ row.content['#row']._entity.body[i].value|raw }}
{% endfor %}

```

# Answer
> 11 votes
I have figured a way using kint.

Inside your views-view-unformatted.html.twig use the following code to display your individual fields:

```
{% for row in rows %}

{{ row.content['#view'].style_plugin.render_tokens[ loop.index0 ]['{{ YOUR_FIELD_NAME }}'] }}

{% endfor %}

```

# Answer
> 7 votes
You need to create three files to override the views using twig files.
1. views-view--foobar.html.twig
2. views-view-unformatted--foobar.html.twig
3. views-view-fields--foobar.html.twig

Purpose of all three files is described below:
1: Default theme implementation for main view template.
2: Default theme implementation to display a view of unformatted rows.
3: Default view template to display all the fields in a row.

You should use "views-view-fields--foobar.html.twig" to output each of your field on views.

Below is a sample:

```
<li>
<p>{{ fields.title.content }}</p> // Title field
<p>{{ fields.body.content }}</p> // Body field
<span>{{ fields.created.content }}</span> // Node authored date field
<a href="{{ fields.path.content }}" class="readmore"> read more </a> // Link to actual page
</li>

```

# Answer
> 5 votes
Below is the sample code to access field values in views-view-unformatted.html.twig file -

```
{% for row in rows %}
  {% set photo = file_url(row['content']['#row']._entity.field_page_photo.entity.fileuri) %}
  <li><img src={{ photo }} class="img-responsive img-circle"></li>
{% endfor %}

```

# Answer
> 1 votes
You can simply add your field value like this

```
{% for key, item in rows %}
  {{ view.style_plugin.getField(key, 'field_name') }}
{% endfor %}

```

# Answer
> 0 votes
From my experience, there's no easy way to twig in views-views-unformatted--view-.html.twig a value from fields not part of the entity structure.

Very to print a `text (plain)` field. So painfull to print a `flag_field`, `entity_reference` and so on.

Having to achieve this without going through the whole view core code, I had to build this hack:

1. add a fake plain text field entity
2. hook the view field value in a custom module:
3. twig (finally) the desired value in template

More details here https://drupal.stackexchange.com/a/288316/13760

---
Tags: views, theming, 8
---


# Question
Title: Node form field validations on change with AJAX
I'd like to be able to trigger the validations for a field, including relevant entity constraints, on a change (or equivalent) event for the field using AJAX. But I cannot figure out how to make that happen. It looks like the validation code is being called, but validations are disabled in form state (limit\_validation\_errors is set to \[\]). I can hack that but I assume it's doing that for a reason.

I would have thought that this is a pretty common thing to do but either no or I am failing at picking the right search keywords.

# Answer
This can be done, it seems, though you have to watch out for the details of the kind of field you are validating.

On the same element of the form where you create your #ajax settings, you can use #limit\_validation\_errors to validate the fields your ajax callback will replace:

```
$item['#limit_validation_errors'] = [ ['field_1'], ['field_2'] ];

```

At first I thought it was ignoring this, but it turns out that the issue was with what I was replacing in the form. For example, each item in a multivalue email field is inside a .js-form-item div, and that's what rendering the element will create. But the "drupal-data-selector" value only applies to the tag inside the div. If I replace the whole field, rather than the element that triggered the ajax callback, the validation errors show up. I'm sure other kinds of elements will have other quirks.
> 0 votes

---
Tags: forms, ajax
---


# Question
Title: How to retrieve all taxonomy term using json api
I want to retrieve all taxonomy term name using json api.

I have tried:

```
http://local-tes/jsonapi/taxonomy_term/specialties

```

but its only return 50 values, I want to fetch all taxonomy terms values.

# Answer
> 1 votes
See https://www.drupal.org/docs/core-modules-and-themes/core-modules/jsonapi-module/pagination#s--cant-i-set-a-page-limit-higher-than-50:

> **Why can't I set a page limit higher than 50?**
>
> First, read the example given above. Understand that JSON:API must run individual access checks for every entity in a response. Second, understand that the JSON:API module aims to be "zero configuration." You shouldn't have to install, alter or configure anything to use the module.
>
> The reason for this is to protect your application from a DDoS attack. If a malicious API client set a page limit of 200,000 resources, the JSON:API module would need to run entity access checks for every one of those entities. This would quickly lead to out-of-memory errors and slow responses. The server needs to set a maximum. The limit of 50 was somewhat arbitrarily chosen as a nice round number.
>
> Please understand that there have been many long conversations around this decision and a compromise had to be made between support burden, sane defaults, and frontend performance. While the JSON:API module maintainers do understand that this may not be ideal for every use case, they're confident that if your client follows the recommendations in these docs, it should have little to no impact on you :)

There is the JSON:API Page Limit module and also JSON API Defaults (part of the popular JSON:API Extras module) to change the limit.

After you have installed the JSON API Defaults module go to

http://example.com/admin/config/services/jsonapi/add/resource\_types/taxonomy\_term/\[vocabulary\]

and change the page limit at the bottom of the config form.

Then you can request a higher number of items with the query parameter `page[limit]`:

http://example.com/jsonapi/taxonomy\_term/\[vocabulary\]?page\[limit\]=1000

---
Tags: taxonomy-terms
---


# Question
Title: How can I set a Rules action to unpublish a comment when a specific flag is set?
I'm attempting to create a flag that will unpublish a comment when the flag is set on that comment.

I'm attempting to use Rules, Flag, and Rules Flag to achieve this.

The comment type is default 'comment' I'm calling the flag 'unpublish\_publish' The flag is global

Where I get stuck is on the Actions portion of the rule creation. For the trigger event I have: After flagging a comment of type Default comments Machine name: rules\_flag\_entity\_flagged:comment--comment

For condition, I have...
Entity is of type Parameters: entity: comment, type: comment

For actions, I have... Set a data value Parameters: data: comment.status.value, value: 0

Something must be wrong. a) Where should I be identifying which flag is involved? There doesn't seem to be any way to do it under conditions. b) I get an error when the rule is enabled...

```
Drupal\flag\FlagService::getFlagging(): Argument #1 ($flag) must be of type Drupal\flag\FlagInterface, null given, called in ...modules/contrib/rules_flag/src/Plugin/Condition/EntityIsFlagged.php on line 57 in Drupal\flag\FlagService->getFlagging() (line 93 ...

```

Has anyone achieved this in D8+ and can straighten me out?

# Answer
> 2 votes
> a) Where should I be identifying which flag is involved?
>
> But there is still a problem: there still doesn't seem to be any way to specify which flag is supposed to trigger the rule.

Yes, currently there is no way to do it... I mean... until a few moments ago, as I have made a patch that adds a "Flag has ID" conditional.

> b) I get an error when the rule is enabled...

Clear the cache. If that still doesn't do, make sure you disable the rules that rules\_flag pre-installs, as one of them also caused me an "argument #1" error.

---
Tags: rules, flags
---


# Question
Title: How to implement decoupled user registration with React / jsonapi?
I have built a React app that uses JSON:API to pull in data, but now I want to implement user registration.

JSON:API doesn't do user registration because it isn't a CRUD operation.

However, the links above explain that core provides a REST endpoint for handling user registration.

The documentation gives this example:

```
curl \
  --header "Content-type: application/json" \
  --request POST http://drupal.d8/user/register

```

But this example seems incomplete-- for example, where is the username?

My website is configured with the Email Registration module and only an email address is required to register, but where do I submit the email address?

**EDIT: If you're answering this question, I will accept an answer that uses core's username/email address combo for registration; it doesn't have to be specific to the Email Registration module. The problem is that I can't find an example of how to register users with JSON:API, and there is no documentation.**

Here's the code I tried in React:

**UserRegistrationForm.tsx**

```
import * as React from 'react';
import { useForm } from 'react-hook-form';
import { IonButton } from '@ionic/react';
import { baseUrl, basicHeaders } from '../utils/globals';
import handleErrors from '../utils/fetchHandleErrors';

interface InterfaceRegistrationFormInput {
  email: string;
}

const UserRegistrationForm: React.VFC = () => {
  const { register, handleSubmit, errors } = useForm<InterfaceRegistrationFormInput>();

  const onSubmit = (formData: InterfaceRegistrationFormInput) => {
    fetch(`${baseUrl}/user/register`, {
      method: 'POST',
      headers: basicHeaders,
      body: formData,
    })
      .then(handleErrors)
      .catch((error) => Promise.reject(new Error(error)));
  };

  return (
    <>
      <form onSubmit={handleSubmit(onSubmit)}>
        <label htmlFor="email">
          Email address
          <br />
          <input
            name="email"
            type="email"
            ref={register({ required: true })}
          />
        </label>
        <IonButton type="submit">Register</IonButton>
      </form>
    </>
  );
};

```

# Answer
To register user using core Rest Module you need 5 steps:

Step 1: Download and enable Rest UI module, this module provides a user interface for administrating Rest Endpoints. Using this module's configuration (admin/config/services/rest) Enable User Registration

Step 2: Then in account setting configuration you should allow user to create account, and if you want user to be added using user name and password you will need to uncheck require email verification else leave it checked.

Step 3: Now you need to allow anonymous user to access user registration (admin/people/permissions/anonymous):

Step 4: Another step to take is to get a xcsrf token from drupal cause you need to use a post method for user creation and post methods are unsafe methods, so drupal protects them using token, to get a XCSRF Token simply call `/session/token` endpoint.

Step 5: Now final step is to ask for user creation:

Method: `POST`

Endpoint: `user/register?_format=json`

Header:

```
Content-Type: application/json
Accept: application/json
X-CSRF-Token: "XCSRF TOKEN PROVIDED BY DRUPAL"

```

Body:

```
{
  "name": [{"value": "USERNAME"}],
  "mail": [{"value": "EMAIL"}],
  "pass":[{"value": "PASSWORD"}]
}

```

and that's it.

PS: Remember that if you have not unchecked "require email verification" in account settings form then you should exclude `pass` from your request body. in this case user needs to navigate to your drupal site for email verification which in case of decoupled scenario it sounds wired. so I highly recommend to uncheck this option in account settings configuration.

Another PS: If you need to require user to confirm his/her email, then you can use a simple solution, like add a verify code to user (prevent user access to this field using Field Permissions module) then in hook\_user\_presave you can assign a code to it, send user an email containing this code and finally deactivate user) , finally you will need a custom Rest endpoint so user can fill a form containing email field and code and if code matches the one you sent you can activate user's account.
> 6 votes

# Answer
This is surprisingly difficult given all the good press decoupled Drupal has gotten over the past few years-- user registration in Core has bugs that make it impossible to use without patching.

Building on Alireza Tabatabaeian's answer, this answer is specifically for

1. Using the Email Registration module.
2. Requiring users to verify their email addresses.
3. Doing it in React/TypeScript (code example at the end)

**Detailed steps**

First, enable Rest UI.

Navigate to `/admin/config/services/rest`.

Enable `User registration`.

Configure as follows:

* Granularity: `Resource`
* Methods: `POST`
* Accepted request formats: `json`
* Authentication providers: `cookie`

Next, at `/admin/people/permissions#module-rest`, give the anonymous user `Access POST on User Registration resource` permission.

**Testing on Postman**

You should now be able to test on Postman.

Here's how to format the request.

1. Select `POST`.
2. For the url, use `http://www.example.com/user/register?_format=json`.
3. For the headers:

* Content-Type: application/json
* Accept: application/json
* X-CSRF-TOKEN: (use value from `GET` to `http://www.example.com/session/token`

For the request body:

**raw** format

And then use this value:

```
{
    "name":{"value":"test"},
    "mail":{"value":"test@example.com"}
}

```

You will need to add `pass` as well if you are not requiring email verification.

If you are requiring email verification, there is a Core bug that will block all users registered via REST and prevent email validation. You will need the patch from this issue.

**React TypeScript Ionic code example**

**UserRegistrationForm.tsx**

```
import * as React from 'react';
import { useForm } from 'react-hook-form';
import {
  IonButton, IonItem, IonLabel, IonInput,
} from '@ionic/react';
import { baseUrl, restHeaders } from '../utils/globals';
import handleErrors from '../utils/fetchHandleErrors';
import { fetchWithCSRFToken } from '../utils/fetch';
import ErrorSummary from '../utils/ErrorSummary';

interface InterfaceRegistrationFormInput {
  email: string;
}

const UserRegistrationForm: React.VFC = () => {
  const {
    register, handleSubmit, errors, setError,
  } = useForm<InterfaceRegistrationFormInput>();

  const onSubmit = (formData: any) => {
    const myRegData = {
      name: {
        value: Date.now(),
      },
      mail: {
        value: formData.mail,
      },
    };

    fetchWithCSRFToken(`${baseUrl}/user/register?_format=json`, {
      method: 'POST',
      headers: restHeaders,
      body: JSON.stringify(myRegData),
    })
      .then(handleErrors)
      .then((response) => {
        console.log('response', response);
      })
      .catch((error: any) => {
        if (error.message === 'Unprocessable Entity') {
          setError('email', {
            type: 'manual',
            message: 'You have already registered.',
          });
        } else {
          setError('email', {
            type: 'manual',
            message: 'Unknown error.',
          });
        }
      });
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <IonItem>
        <ErrorSummary errors={errors} />
        <IonLabel position="stacked">
          Email address
        </IonLabel>
        <IonInput
          name="mail"
          type="email"
          ref={register({ required: true }) as any}
        />
      </IonItem>
      <IonButton type="submit">Register</IonButton>
    </form>
  );
};

export default UserRegistrationForm;

```

**globals.tsx**

```
export const restHeaders: HeadersInit = new Headers({
  'Content-Type': 'application/json',
  Accept: 'application/json',
});

```

**fetchHandleErrors.tsx**

```
// Throw exceptions instead of fetch default behavior.
// https://www.tjvantoll.com/2015/09/13/fetch-and-errors/
export default function handleErrors(response: Response): Response {
  if (!response.ok) {
    throw new Error(response.statusText);
  }
  return response;
}

```

**fetch.tsx**

```
export const fetchWithCSRFToken = (fetchUrl: string, fetchOptions: any) => {
  if (!fetchOptions.headers.get('X-CSRF-Token')) {
    const csrfUrl = `${baseUrl}/session/token`;
    return fetch(csrfUrl)
      .then((response) => response.text())
      .then((csrfToken) => {
        // console.log('csrfToken', csrfToken);
        fetchOptions.headers.append('X-CSRF-Token', csrfToken);
        return fetch(fetchUrl, fetchOptions);
      });
  }
  return fetch(fetchUrl, fetchOptions);
};

```

**ErrorSummary.tsx**

```
import React from 'react';
import { ErrorMessage } from '@hookform/error-message';
import { FieldErrors } from 'react-hook-form';

type ErrorSummaryProps<T> = {
  errors: FieldErrors<T>;
};

// https://www.carlrippon.com/react-hook-form-validation-errors/
function ErrorSummary<T>({ errors }: ErrorSummaryProps<T>) {
  if (Object.keys(errors).length === 1) {
    return null;
  }
  return (
    <div className="error-summary">
      {Object.keys(errors).map((fieldName) => (
        <ErrorMessage errors={errors} name={fieldName as any} as="div" key={fieldName} />
      ))}
    </div>
  );
}

export default ErrorSummary;

```
> 2 votes

# Answer
This seems not possible without core's RESTful Web Services module enabled.

You need to specify the \_format in the url to be routed right, like: `/user/register?_format=hal_json`

I assume your *basicHeaders* contain:

```
Accept: application/json
Content-Type: application/json

```

Plus make sure to give the permission **Access POST on User registration resource** to anonymous users.

And make the body look like:

```
{
 "_links":{"type":{"href":"${baseUrl}/rest/type/user/user"}},
 "mail":{
   "value":"user@example.com"
 }
}

```

(Assuming the email registration module re-uses the core's field name.)

You can also use \_format=json and skip the "\_links" JSON property.

Source another documentation page and the grand d.o. issue.

> I updated also the documentation you linked. (Added ?\_format=json)
> 0 votes

# Answer
There is a JSON:API User Resources module that provides an endpoint for doing user registration.

I couldn't get this to work with the Email Registration module, but it may be a good solution for others so I'll note it here.
> 0 votes

# Answer
Currently, I'm at the same step like you, enable user registration on a decoupled Drupal 9 Backend

1. I've disabled drupals email verification, so we submit with a password. I'll implement something customized for email verification later.
2. Enable permission `Access POST on User registration resource` on `/admin/people/permissions` for **Anonymous** user.
3. Enable `User registration` on `/admin/config/services/rest`

```
curl --location --request POST 'http://localhost:54412/user/register?_format=json' \
--header 'Content-Type: application/json' \
--data-raw '{
 "mail": [
     "iglu@ad.com"
 ],
 "name": [
     "iglu"
 ],
 "pass":[
     "pass"
 ]
}'

```

Images
> 0 votes

---
Tags: users, 8
---


# Question
Title: Going from 9.5.1 to 10.0.1 keep getting same error message regarding Twig
I've tried going to 10.0.1 using Composer and then tried updating to 10.0.1 and get the same error message....

The website encountered an unexpected error. Please try again later.

Error: Class "Twig\_Extension" not found in include() (line 12 of /home/customer/www/wiulibraries.org/public\_html/video1/modules/entity\_embed/src/Twig/EntityEmbedTwigExtension.php).

include() (Line: 571) Composer\Autoload\includeFile('/home/customer/www/wiulibraries.org/public\_html/video1/modules/entity\_embed/src/Twig/EntityEmbedTwigExtension.php') (Line: 428) Composer\Autoload\ClassLoader-\>loadClass('Drupal\entity\_embed\Twig\EntityEmbedTwigExtension') is\_subclass\_of('Drupal\entity\_embed\Twig\EntityEmbedTwigExtension', 'Twig\Extension\ExtensionInterface') (Line: 181) Drupal\Core\DependencyInjection\Compiler\TaggedHandlersPass-\>processServiceCollectorPass(Array, 'twig', Object) (Line: 116) Drupal\Core\DependencyInjection\Compiler\TaggedHandlersPass-\>process(Object) (Line: 73) Symfony\Component\DependencyInjection\Compiler\Compiler-\>compile(Object) (Line: 721) Symfony\Component\DependencyInjection\ContainerBuilder-\>compile() (Line: 1307) Drupal\Core\DrupalKernel-\>compileContainer() (Line: 911) Drupal\Core\DrupalKernel-\>initializeContainer() (Line: 477) Drupal\Core\DrupalKernel-\>boot() (Line: 679) Drupal\Core\DrupalKernel-\>handle(Object) (Line: 19)

Any help would be appreciated..

# Answer
> 2 votes
You must use the most current dev version of entity\_embed because the released version, 8.x-1.3, uses the old Twig\_Extension.

A commit in December 2022 removed the usage of Twig\_Extension but this has not yet been released.

---
Tags: 10
---


# Question
Title: How can I prevent a page with PHP content getting flagged in Security Review "Dangerous tags in content" check?
I am using Drupal 7. I have a page that has a PHP body that I know does not have any dangerous tags. According to the README.txt file in Security Review I need to add this to the "security\_review\_known\_risky\_fields" system variable ? Can somebody provide an example on how to do this? I am not sure exactly what the entry in the variable table should look like.

# Answer
> 2 votes
In settings.php add the following:

```
$conf['security_review_known_risky_fields'] = implode(
  ',',
  array(
    'xxx',
    'yyy',
    'zzz'
  ),
);

```

...where 'xxx', 'yyy', and 'zzz' are the content hash strings shown for each problematic file in the Security Review report.

# Answer
> 1 votes
The README says to create "a SHA-256 hash of the entity\_id, entity\_type, and field contents". It looks like you have to call `hash('sha256', $entity_id.$entity_type.$field_contents)` and save that in the `security_review_known_risky_fields` string variable, which can be done in settings.php. If there are multiple fields you want to allow, separate their respective hashes with commas.

---
Tags: 7, security
---


# Question
Title: Testing equality of two variables - one is entity reference
I'm new to Drupal theming and twig, so apologies for asking a simple question, but it's driving me crazy. I can't find the solution.

I'm trying to test the equality of field from a Custom content type - field\_program\_level - that's an Entity reference type. field\_program\_level has two possible values : G and UG.

I've tried everything I know and my code doesn't work. My current code is:

```
{% set yy = content.field_program_level[0]|render %}
{% set graduate = 'G' %}
{% if yy is same as(graduate) %}
<p> Success! yy was created and equal to {{ yy }} </p>
{% else %}
<p> Failure! {{ yy }} does not = {{ graduate }} </p>
{% endif %}

```

I'm assuming that because field\_program\_level is a entity reference it's some type of array or object.

yy = {{ yy }}

outputs "G" as it should, but "is same as" fails.

I tried using {{ node.field\_program\_level.0.value }} but it doesn't work. I've also tried using filters |render and |trim.

Any suggestions?

# Answer
> 1 votes
Using the `node` object instead of the `content` render array is a good idea, but a reference field doesn't contain a value. You probably want to test against the label of the referenced entity:

```
{% set yy = node.field_program_level.0.entity.label %}
{% set graduate = 'G' %}
{% if yy is same as(graduate) %}

```

---
Tags: theming
---


# Question
Title: How to get webform url object, if I have webform machine name and webform path
I have webform path and webform machine name, how can I get url object of this webform?

# Answer
> 5 votes
You can use the same route as for other entities: `$webform_url = Url::fromRoute('entity.webform.canonical', ['webform' => 'my_webform_id']);`

---
Tags: webforms, 9, uri
---


# Question
Title: Problem with Adding new fields with Ajax call to a custom form
I have a simple form where I am trying to add a couple of fields to it when the user clicks a button using an ajax callback. Here is what I have:

```
public function buildForm($form, FormStateInterface $form_state)
  {

    $form['add_fields'] = [
      '#type' => 'button',
      '#value' => 'Add new fields',
      '#ajax' => [
        'callback' => [$this, 'ajax_callback'],
        'disable-refocus' => FALSE,
        'event' => 'click',
        'wrapper' => 'new-fields-wrapper',
        'progress' => [
          'type' => 'throbber',
          'message' => $this->t('Verifying entry...'),
        ],
      ],
    ];

    // Wrapper for new fields
    $form['new_fields_wrapper'] = [
      '#type' => 'container',
      '#attributes' => ['id' => 'new-fields-wrapper'],
    ];

    return $form;
  }

```

As you see, it's a very simple form and I am defining a wrapper element inside where I would like to add the new fields.

Here is my ajax callback function where I am basically adding 3 new fields:

```
 public function ajax_callback($form, FormStateInterface $form_state)
  {

    $form['new_fields_wrapper']['new_field_1'] = [
      '#type' => 'textfield',
      '#title' => 'New Field 1',
    ];
    $form['new_fields_wrapper']['new_field_2'] = [
      '#type' => 'select',    '
      #title' => 'New Field 2',
      '#options' => [1 => 'Option 1', 2 => 'Option 2'],
    ];
    $form['new_fields_wrapper']['new_field_3'] = [
      '#type' => 'checkbox',
      '#title' => 'New Field 3',
    ];

    return $form['new_fields_wrapper'];
  }

```

And finally I have a submit form function where I'd like to get the values entered for the new fields:

```
public function blockSubmit($form, FormStateInterface $form_state)
  {
    $values = $form_state->getValues();
  }

```

I have two problems here:

1. When I click on the button to add the new fields through the ajax callback, it does not add the fields. I made sure that the callback function is actually called by adding some logging. However, it doesn't add the new fields. As I explored with the devtools, I realized that when the form is displayed, the wrapper element does not exist in the DOM. I added a hidden field to it like this: `$form['new_fields_wrapper']['hidden'] = [ '#type' => 'hidden', '#value' => 0, ];`

This made the wrapper appear in the DOM and now the button click works and the fields are added. Is this how I am supposed to handle it? In all my research, there was no mention of having to include a field in the wrapper in the original form.

2. With the new fields added, when I enter values in them and hit the form submit button, the new field values are not included in the `$form_state->getValues()`. How can I get the values entered in the new fields with the form submit?

Thanks a lot in advance for any help.

# Answer
> 1 votes
You cannot add form elements in ajax callbacks. Drupal caches the form before the callback, so if you add elements in the callback, they are not part of the cache, and any values submitted by those elements is disregarded as a security measure.

The solution is to put these fields in your form definition:

```
public function buildForm($form, FormStateInterface $form_state)
  ...
  if (!empty($form_state->getValues()) {
    $form['new_fields_wrapper']['new_field_1'] = [
      '#type' => 'textfield',
      '#title' => 'New Field 1',
    ];
    $form['new_fields_wrapper']['new_field_2'] = [
      '#type' => 'select',    '
      #title' => 'New Field 2',
      '#options' => [1 => 'Option 1', 2 => 'Option 2'],
    ];
    $form['new_fields_wrapper']['new_field_3'] = [
      '#type' => 'checkbox',
      '#title' => 'New Field 3',
    ];
  }
  ...
}

```

---
Tags: forms, ajax, 9
---


# Question
Title: Hide/remove "Last" label/icon in views pager
I don't want my user to click the "Last" label on the views pager, but I can't find a way to remove this "Last" label even I leave the "Last page link text" field empty, I don't want to use the mini pager, so in the full pager, how can we remove the "Last" label/icon ? Thanks

# Answer
You can override pager.html.twig in your theme, removing the section that adds the 'last' link:

```
{% if items.last %}
  <li class="pager__item pager__item--last">
    <a href="{{ items.last.href }}" title="{{ 'Go to last page'|t }}"{{ items.last.attributes|without('href', 'title') }}>
      <span class="visually-hidden">{{ 'Last page'|t }}</span>
      <span aria-hidden="true">{{ items.last.text|default('Last »'|t) }}</span>
    </a>
  </li>
{% endif %}

```
> 3 votes

---
Tags: views, 9
---