# Question
Title: Debugging with var_dump -> where does the output go?
Me and a colleague had a D7 problem to handle, $\_SESSION were being lost for anonymous users. Because this is all happening on a staging server in a corporate environnment, devel module has been ripped out in preparation for the push to production. My colleague starts inserting `var_dumps()` in a forms validate function, but the results don't show to screen.

He figures the validation is not being called, but I tell him about how Drupal suppresses output during rendering, I have experienced this many times. Adding a `die` in the validate function confirmed that the function was in fact being executed, except the question remains -\> why / how is output suppressed when echoing / var\_dumping in functions?

Debugging with var\_dump is probably not the most recommended or effective method, I just want to know what it is that prevents ouptput.

# Answer
Usually the `var_dump()` works but gets hidden below the theme. This is because theme rendering comes last.

I could go into it more, but basically just install Devel and use `dpm()` for your variable dumps. It prints them in a Drupal-style message. You'll love it.
> 5 votes

# Answer
you'll see it if you exit execution:

```
var_dump( $your_variable );
exit();

```
> 0 votes

---
Tags: 7
---


# Question
Title: How can I create the views pager on top and bottom of the view?
I need two view pagers / pagination to sandwich the view content or view results.

Is it possible to duplicate view pagers/pagination ?

What i've done is just printed out the pagers in the template twice; however, that requires me to hardcode the pager.

I need a little more flexibility because I'm required to build / place the top pager in different spots on different pages.

Could this be accomplished with views display (suite) somehow and a code field? I've attempted one and had no luck.

# Answer
I think you are on the right track by editing the views template files. Do you know you can have a different template for each view, or each views display? When you are editing your view there is a link called "theme information" that will help you figure out how to name the templates.

Now, If you mean you need to have the pager in different places on page 1 of this display vs page 2 of the same display, you will have to dig inside the view object to figure out which page you're on in order to figure that out.

I also found this tutorial while Googling the answer: http://www.adesignforlife.net/articles/drupal-tutorials/solution-how-print-pager-drupal-views-block
> 0 votes

# Answer
I've done this recently for a site. First, you wanna enable twig debugging. Write the file web/sites/development.services.yml with the following content:

```

parameters:
  http.response.debug_cacheability_headers: true
  twig.config:
    debug: true
    auto_reload: true
    cache: false
services:
  cache.backend.null:
    class: Drupal\Core\Cache\NullBackendFactory

```

This will give you hints about available template filenames, in the source code (ctrl+shift+C in the browser to view the source code). Then, in the appropriate template file which for me was `templates/views/views-view.html.twig`:

```

  {% if pager %}
    {{ pager }}
  {% endif %}
  {% if rows %}
    <div class="view-content row">
      {{ rows }}
    </div>
  {% elseif empty %}
    <div class="view-empty">
      {{ empty }}
    </div>
  {% endif %}
  {% if pager %}
    {{ pager }}
  {% endif %}

```
> 0 votes

---
Tags: 7, views, paging, display-suite
---


# Question
Title: How to add internal path in *.links.menu.yml
I am trying to add an internal link to admin toolbar but I am not able to achieve it.

According to documentation we add an internal link in `*.links.menu.yml` in the below manner but the link is not being appeared in the toolbar.

```
hello_world.admin2:
  title: 'Hello module settings'
  description: 'example of how to make an admin settings page link'
  parent: system.admin_config_development
  url: internal:/node/123

```

I tried the following variants as well but none works. `url: 'internal:/node/123'` or `uri: internal:/node/123` or `uri: 'internal:/node/123'` .

But the following works `url: http://localhost/node/123` .

Can anyone suggest me a way to create a menu link in `*.links.menu.yml` file.

**Use case** : I want to provide easily accessible link to user to access one particular page. It is not a route. I am aware of other way to create menu link by using `MenuLinkContent::create` method. But trying to figure out why above method is not working.

# Answer
I don't know thy this doesn't work (it is a valid input for `Drupal\Core\Url::fromUri`), but `/node/123` actually has a route:

```
hello_world.admin2:
  route_name: entity.node.canonical
  route_parameters:
    node: 123

```

Even though they are valid inputs, it is generally a good idea to avoid `internal:` URLs if you can use something better. "Something better" is either a route name (in the context of `links.yml` files) or an entity scheme `entity:node/123` (in the context of storing links in the DB). AFAIK `internal:` was meant for local unrouted URLs like e.g. `internal:/robots.txt`
> 3 votes

# Answer
@miststudent2011 I think the idea you're missing is that a menu link offers *either* a route *or* a url.

From the Drupal 10.1 Menu API intro page:

> links point to routes or URLs.

From the Drupal 10.1 documentation for function hook\_menu\_links\_discovered\_alter:

> **route\_name**: (optional) The route name to be used to build the path. Either the route\_name or url element must be provided.
>
> **route\_parameters**: (optional) The route parameters to build the path.
>
> **url**: (optional) If you have an external link use this element instead of providing route\_name.

Put simply, use route\_name for internal links. Use url for external links. Not both!
> 0 votes

---
Tags: routes, 9
---


title: Translatable custom entity

text:
# Question
Title: Translatable custom entity
Was there any significant change in how translatable custom entities are updated leading up to Drupal 10.1? There are a few questions here that deal with the question but it no longer seems to work. To recap, I have a custom entity *already populated with data* that I want to make translatable now. I have made all the necessary changes: the entity itself is annotated to be translatable, entity key added, two langcode fields added, translation handler added. Actually, if I temporarily remove the data and use Devel's `entup`, it works. Still, I want to make it able to do the correct data migration.

I have both update functions in place:

```
function MODULE_update_VERSION() {
  $entity_definition_update_manager = \Drupal::entityDefinitionUpdateManager();
  $field_storage_definition = $entity_definition_update_manager->getFieldStorageDefinition('my_field', 'my_entity');
  $field_storage_definition->setTranslatable(TRUE);
  $entity_definition_update_manager->updateFieldStorageDefinition($field_storage_definition);
}

```

and

```
function MODULE_post_update_VERSION(&$sandbox) {
  $definition_update_manager = \Drupal::entityDefinitionUpdateManager();
  $entity_type = $definition_update_manager->getEntityType('my_entity');
  $entity_type->set('translatable', TRUE);
  $entity_type->set('data_table', 'my_entity_field_data');

  /** @var EntityLastInstalledSchemaRepositoryInterface $last_installed_schema_repository */
  $last_installed_schema_repository = \Drupal::service('entity.last_installed_schema.repository');
  $field_storage_definitions = $last_installed_schema_repository->getLastInstalledFieldStorageDefinitions('my_entity');
  $field_storage_definitions['my_field']->setTranslatable(TRUE);

  $field_storage_definitions['langcode'] = BaseFieldDefinition::create('language')
    ->setName('langcode')
    ->setLabel(t('Language code'))
    ->setDescription(t('The language code.'))
    ->setStorageRequired(TRUE)
    ->setDefaultValue('x-default')
    ->setTranslatable(TRUE);

  $field_storage_definitions['default_langcode'] = BaseFieldDefinition::create('boolean')
    ->setName('default_langcode')
    ->setLabel(t('Default Language code'))
    ->setDescription(t('Indicates if this is the default language.'))
    ->setTargetEntityTypeId('my_entity')
    ->setTargetBundle(NULL)
    ->setTranslatable(TRUE)
    ->setRevisionable(TRUE)
    ->setDefaultValue(TRUE);

  $definition_update_manager->updateFieldableEntityType($entity_type, $field_storage_definitions, $sandbox);
}

```

When updating (either Drush or UI), both update functions are picked up, however, while the regular update succeeds, the post update function gives a *Missing langcode field* error and stops.

The `langcode` field is obviously right there, to be created. I thought about splitting the action into two upgrade steps, first `langcode` and `default_langcode`, then doing the migration, but while the fields do appear in the base table then, the error message is the same.

So, the question is whether there was any change, intentional or not in later Drupal versions that makes this approach fail now?

# Answer
Indeed, the items above are no longer sufficient, some others have to be specified as well:

```
  $definition_update_manager = \Drupal::entityDefinitionUpdateManager();
  $entity_type = $definition_update_manager->getEntityType('my_entity');
  $entity_keys = $entity_type->getKeys(); // <<<
  $entity_keys['langcode'] = 'langcode'; // <<<
  $entity_keys['default_langcode'] = 'default_langcode'; // <<<
  $entity_type->set('entity_keys', $entity_keys); // <<<
  $entity_type->set('translatable', TRUE);
  $entity_type->set('data_table', 'my_entity_field_data');

```

The error message is actually misleading, it's not the *field* that's missing but its *key.*

Also (this didn't seem to be necessary earlier):

```
  $field_storage_definitions['langcode'] = BaseFieldDefinition::create('language')
   ->setName('default_langcode')
    ->setLabel(t('Default Language code'))
    ->setDescription(t('Indicates if this is the default language.'))
    ->setTargetEntityTypeId('my_entity') // <<<
    ->setTargetBundle(NULL)
    ->setTranslatable(TRUE)
    ->setRevisionable(TRUE)
    ->setDefaultValue(TRUE);

```

Addendum:

```
->setDefaultValue('x-default')

```

is very questionable. Some other sources mentioned it but it doesn't seem to work. Proceed with care, maybe use the actual default language code of your site. Drupal used to call it `und` some time ago, I don't know if that would still work here or not.
> 2 votes

---
Tags: entities, i18n-l10n, 10
---


# Question
Title: How can I read a cookie I programmatically set?
I can programmatically set a cookie in a Drupal 9 controller and I can see that cookie in Chrome's developer tools. However, I *cannot* programmatically get that cookie from a hook.

I'm using the *SAML Service Provider* module. I'm extending the `SamlSPDrupalLoginController::initiate()` function with this code to set a cookie.

```
setcookie('stv_saml_idp_id', $idp->get('id'), time() + 86400, '/');

```

That seems to work fine as I can see the cookie in the Chrome developer tools. Unfortunately, when I attempt to get the cookie back with the following code, I get no results.

```
function mymodule_saml_sp_drupal_login_user_attributes_alter($user, array $attributes) {
  // …
  $cookies = \Drupal::requestStack()->getCurrentRequest()->cookies;
  $idp_id = $cookies->get('stv_saml_idp_id');
  //…
}

```

*However*, if (as a test) I embed the same code in a Basic page, I *can* get the cookie.

I have also tried with `$idp_id = $_COOKIE['stv_saml_idp_id'];` but I still could not get the cookie.

How can I read a cookie I programmatically set?

# Answer
Oh... thanks **cilefen**. That was a good question that helped me find the problem :-)

I was writing down the attributes to post in reply when I realised my cookie domain differed from the Drupal session cookie domain by 1 character. *My* cookie domain was:

```
mysub.domain.com

```

Whereas, the session cookie had leading dot like so:

```
.mysub.domain.com

```

So, the solution was to explicitly set the cookie Domain exactly the same as the Drupal session Domain:

```
setcookie('stv_saml_idp_id', $idp->get('id'), time() + 86400, '/', '.mysub.domain.com');

```

Thanks again.
> 4 votes

---
Tags: 9, cookies
---


# Question
Title: A Drupal.behaviors stops working when I update the module
I have checked the field\_ui core module to understand how to update my code, but it doesn't seems to work.

This is the code.

```
(function ($, Drupal, drupalSettings) {
  Drupal.behaviors.custommoduleAnalytics = {
    attach: function (context, settings) {

      console.log('hello world');
    }
  };
})(jQuery, Drupal, drupalSettings);

```

This is the library field code.

```
custommodule_analytics:
  js:
    js/custommodule_library.js: {}
    js/custommodule_analytics.js: {}
  dependencies:
    - core/jquery
    - core/drupal.ajax
    - core/drupal
    - core/drupalSettings
    - core/jquery.once

```

I use `hook_page_attachments()` to load the file.

If I look in the browser inspector, it shows that the file loads when the page is loaded, but I don't see `'hello world'` printed from `console.log()`. The weirdest thing is that this module worked without any issues in version 8.x, and now that I'm updating it to Drupal 9 or 10, it does not work.

# Answer
> 2 votes
Jquery.once doesnt exist in d10 Use core/once

---
Tags: 9, javascript
---


# Question
Title: View not showing result based on taxonomy term contextual filter
I have a view and same in D7 and same I created in Drupal 10 but the output is not as expected. I found in Drupal 10 we don't have Filter Value type in Drupal 10

Below is the Drupal 7 view query:

```
SELECT node.sticky AS node_sticky, node.created AS node_created, node.nid AS nid
FROM node WHERE (( (node.status = 1 OR (node.uid = 96 AND 96 <> 0 AND 1 = 1) OR 1 = 1) AND (node.nid IN  (SELECT tn.nid AS nid
FROM
taxonomy_index tn
WHERE ( (tn.tid = 'Passed numeric value of taxonomy term') ))) ))
ORDER BY node_sticky DESC, node_created DESC;

```

Drupal 10 View query

```
SELECT "taxonomy_index"."sticky" AS "taxonomy_index_sticky", "node_field_data"."created" AS "node_field_data_created", "node_field_data"."nid" AS "nid"
FROM
{node_field_data} "node_field_data"
INNER JOIN (SELECT "tn"."nid" AS "nid"
FROM
{taxonomy_index} "tn"
WHERE "tn"."tid" IN ('6') UNION SELECT "tn"."nid" AS "nid"
FROM
{taxonomy_index} "tn"
INNER JOIN {taxonomy_term__parent} "th1" ON [tn].[tid] = [th1].    [parent_target_id]
WHERE "th1"."entity_id" IN ('Passed numeric value of taxonomy term') UNION SELECT "tn"."nid" AS "nid"
FROM
{taxonomy_index} "tn"
INNER JOIN {taxonomy_term__parent} "th1" ON [tn].[tid] = [th1]. [parent_target_id]
INNER JOIN {taxonomy_term__parent} "th0" ON [th1].[entity_id] =  [th0].[parent_target_id]
WHERE "th0"."entity_id" IN ('6')) "taxonomy_index_depth" ON    node_field_data.nid = taxonomy_index_depth.nid
LEFT JOIN {taxonomy_index} "taxonomy_index" ON node_field_data.nid =  taxonomy_index.nid
WHERE (node_field_data.status = 1 OR (node_field_data.uid = 98 AND 98 <> 0 AND 1 = 1) OR 1 = 1)
ORDER BY "taxonomy_index_sticky" DESC, "node_field_data_created"  DESC
LIMIT 10 OFFSET 0

```

# Answer
I found the taxonomy\_index table have missing data, so records did not show.
> -1 votes

---
Tags: views, theming, 10
---


# Question
Title: How to form_alter a specific webform ajax page based on values of the page before?
We are building a registration form with multiple pages (in ajax mode), on the first page, we select the number of participants and on the next page we are displaying a custom composite form to collect the details per person (name + email).

In the config of the form element it is exported as `multiple__empty_items`:

```
fnc_person_details:
  '#type': site_participants
  '#multiple__empty_items': 2 # <-- this I want to change dynamically
  ...

```

I would like to have Person Count Elements shown on the second page, but are missing the right hook to do so. It looks like this functionality lives somehow in WebformMultiple but I get lost in there.

**Update 1**

We tried to use `site_registration_form_alter`, but it is only called once for the whole form on render - for later pages, it is not called again. Is there a way to hook form\_alter into the ajax request?

**Update 1 End**

Anybody has a hint how to achieve this?

`web/modules/custom/site_registration/src/Plugin/WebformElement/ParticipantsElement.php`

```
<?php

namespace Drupal\site_registration\Plugin\WebformElement;

use Drupal\webform\Annotation\WebformElement;
use Drupal\webform\Plugin\WebformElement\WebformCompositeBase;
use Drupal\webform\Plugin\WebformElementBase;
use Drupal\webform\WebformSubmissionInterface;

/**
 * Provides a 'site_person_count' element.
 * Main logic lies inside the template and the javascrip
 *
 * @WebformElement(
 *   id = "site_participants",
 *   label = @Translation("Participants"),
 *   description = @Translation("Collects name and emails of participants, based on the person count."),
 *   category = @Translation("Site Custom"),
 * )
 *
 * @see \Drupal\webform_example_element\Element\WebformExampleElement
 * @see WebformElementBase
 * @see \Drupal\webform\Plugin\WebformElementInterface
 * @see WebformElement
 */
class ParticipantsElement extends WebformCompositeBase {

  /**
   * {@inheritdoc}
   */
  protected function formatHtmlItemValue(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
    return $this->formatTextItemValue($element, $webform_submission, $options);
  }

  /**
   * {@inheritdoc}
   */
  protected function formatTextItemValue(array $element, WebformSubmissionInterface $webform_submission, array $options = []) {
    $value = $this->getValue($element, $webform_submission, $options);

    $lines = [];
    $lines[] = $value['first_name'] . ' ' . $value['last_name'] . ' - ' . $value['email'];
    return $lines;
  }

}

```

`web/modules/custom/site_registration/src/Element/ParticipantsElement.php`

```
<?php

namespace Drupal\site_registration\Element;

use Drupal\Core\Render\Annotation\FormElement;
use Drupal\webform\Element\WebformCompositeBase;

/**
 * @FormElement("site_participants")
 */
class ParticipantsElement extends WebformCompositeBase
{
  public function getInfo() {
    $properties = parent::getInfo();

    $properties['#theme'] = 'input__site_participants';
    return $properties;
  }

  /**
   * {@inheritdoc}
   */
  public static function getCompositeElements(array $element) {
    $elements = [];
    $elements['first_name'] = [
      '#type' => 'textfield',
      '#title' => t('First name')
    ];
    $elements['last_name'] = [
      '#type' => 'textfield',
      '#title' => t('Last name')
    ];
    $elements['email'] = [
      '#type' => 'email',
      '#title' => t('Email')
    ];

    return $elements;
  }

}

```

`web/modules/custom/site_registration/site_registration.module`

```
<?php

use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element;
use Drupal\node\Entity\Node;

function site_registration_theme() {

  // allowing this module to define the templates

  return [
    'input__site_participants' => [
      'render element' => 'element',
    ]
  ];
}

function template_preprocess_input__site_participants(array &$variables) {
  $element = $variables['element'];

  $variables['count'] = $element['#parents'][count($element['#parents']) - 2] + 1;

  // Copy all accessible element children to content.
  foreach (Element::children($element) as $key) {
    if (!isset($element[$key]['#access']) || $element[$key]['#access']) {
      $variables['content'][$key] = $element[$key];
    }
  }
}

```

# Answer
> 0 votes
So I found a solution, which appears to be solid. As written in my question, `HOOK_form_alter` was for some not obvious reason not called in the ajax requests, but during my research I found the hook\_event\_dispatcher module which offers a object oriented subscriber based approach to the HOOK callbacks (finally!).

I made it work with this Event Subscriber.

`web/modules/custom/site_registration/src/Subscriber/FormEventSubscriber.php`:

```
<?php

namespace Drupal\site_registration\Subscriber;

use Drupal\core_event_dispatcher\Event\Form\FormAlterEvent;
use Drupal\core_event_dispatcher\FormHookEvents;
use Drupal\webform\Entity\Webform;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

class FormEventSubscriber implements EventSubscriberInterface
{

  public function alterForm(FormAlterEvent $event): void {

    // dump($event->getFormId());

    $form = &$event->getForm();

    if ($form['#webform_id'] ?? false) {

      /** @var Webform $webform */
      $webform = Webform::load($form['#webform_id']);

      if ($webform && in_array('Anmeldung', $webform->get('categories'), true)) {
        $formState = $event->getFormState();

        $personCount = (int) ($formState->getValues()['fnc_person_count'] ?? 1);

        $form['elements']['teilnehmer']['fnc_person_details']['#empty_items'] = $personCount;

        $oldDefaultValue = $form['elements']['teilnehmer']['fnc_person_details']['#default_value'];
        $newDefaultValue = [];

        if (!is_array($oldDefaultValue)) {
          $oldDefaultValue = [];
        }

        for ($i = 0; $i < $personCount; $i++) {
          $newDefaultValue[$i] = array_key_exists($i, $oldDefaultValue) ? $oldDefaultValue[$i] : [];
        }

        $form['elements']['teilnehmer']['fnc_person_details']['#default_value'] = $newDefaultValue;
      }
    }
  }

  public static function getSubscribedEvents()
  {
    return [
      FormHookEvents::FORM_ALTER => 'alterForm'
    ];
  }
}

```

and for the sake of completeness, as none of this is obvious:

`web/modules/custom/site_registration/site_registration.services.yml`:

```
services:
  site_registration.form_subscriber:
    class: Drupal\site_registration\Subscriber\FormEventSubscriber
    tags:
      - { name: event_subscriber }

```

Additionally I configured the number of empty items in the form element to 0, as it adds the number always to the preset fields (which is not what you want in this scenario).

I hope it helps somebody lost in all of this form callbacks and whatnot one day too.

---
Tags: webforms
---


# Question
Title: Access arguments only allow administer and user logged in
I am building a module and used the following code to define a route for a user account.

How do I set the access arguments to only allow administrators and the user himself?

```
$items['user/%/extra-settings'] = [
  'title' => t('extra Settings'),
  'type' => MENU_LOCAL_TASK,
  'access arguments' => ['administer access'],
];

```

# Answer
With the access arguments alone, you cannot give access to user/%/extra-settings to administrator users and the user "owning" the user account.

You need to define your own access callback that checks who is accessing the route.

```
$items['user/%/extra-settings'] = [
  'title' => t('extra Settings'),
  'type' => MENU_LOCAL_TASK,
  'access callback' => 'mymodule_extra_settings_access',
  'access arguments' => [1],
];

```

```
function mymodule_extra_settings_access($account) {
  global $user;

  if (user_access('administer users')) {
    // The route is accessed by an administrator user with
    // the permission to administer users.
  }
  elseif ($account->uid == $user->uid) {
    // The route is accessed by the user who "owns" the user account.
  }
}

```

The permission to check depends on which administrator user should access the route. The code I used is for the case the administrator user is a user who can administer users. In the case the administrator user who can access the route is the user #1, it is sufficient to replace `user_access('administer users')` with `$user->uid == 1`.
> 1 votes

---
Tags: 7, authentication-authorization
---


# Question
Title: How to have a different hero image per node?
What we want: Users should be able to choose an image, add call to action links, and a few other options when setting up a hero for the specific page they are creating. We have three different content types we allow this on currently, basic pages and two custom content types we've created.

Current solution: We have a paragraph with the fields they can change such as layout (how they want the image, call to action links, etc. to be styled), which image they want to use, the links (if any) to be rendered on top of the image, heading, caption, and a few others. This paragraph is referenced on the content types by an entity reference field and then when they create whichever content type, they change all the fields as usual. We have different twig templates and css files to render the images, links, etc. different based on the layout they choose. Since we want the hero image to render in a different part of the page, not within the content of the node, we are using node.field\_name within the page.html.twig template to render it in the section of the page we want.

Current problem: The hero is dynamic per page and is rendering as expected but the changes are not showing in the node revisions. The published version of the page shows the correct hero, the /latest version of the node is showing the updated/correct hero when a draft has been created, but when we go to the node revisions and click the latest draft there (links such as node/31366/revisions/1623918/view), it is showing the same hero settings as the published revision.

Related modules we are using: Content moderation, entity\_reference\_revisions, paragraphs

I added an image of the editing experience, I couldn't get the entire paragraph but that is most of it. I also added an image of what the paragraph looks like rendered, the full image was too large to upload here so it is a smaller version than what is actually shown on the site but too large to attach here.

I've researched current issue with paragraph revisions and node revisions but can't seem to find a patch or any fixes to the issues we're having. If someone could help me with a better solution or sees something that we're doing wrong, we'd really appreciate help/advice. Thanks!

# Answer
You are asking for a better solution, this would be a hero block instead of hard-coding the hero image in the page template. If your block is using the node route context it automatically loads the node revision.

If you want to get the current solution working, try this code in a preprocess hook:

*mytheme.theme*

```
function mytheme_preprocess_page(&$variables) {
  $node = \Drupal::routeMatch()->getParameter('node_revision');
  if ($node) {
    $variables['node'] = $node;
  }
}

```
> 2 votes

---
Tags: nodes, paragraphs
---


# Question
Title: Displaying parent field value in field.html.twig template from nested paragraphs
See attached please. Using field.html.twig and paragraph.html.twig, Paragraphs 8.x-1.16 Stable release and Drupal 9.5.10

field.html.twig (specifically: field--paragraph--sidebar-button-repeater.html.twig):

```
{#
/**
 * @file
 * Theme override for a field.
 *
 * To override output, copy the "field.html.twig" from the templates directory
 * to your theme's directory and customize it, just like customizing other
 * Drupal templates such as page.html.twig or node.html.twig.
 *
 * Instead of overriding the theming for all fields, you can also just override
 * theming for a subset of fields using
 * @link themeable Theme hook suggestions. @endlink For example,
 * here are some theme hook suggestions that can be used for a field_foo field
 * on an article node type:
 * - field--node--field-foo--article.html.twig
 * - field--node--field-foo.html.twig
 * - field--node--article.html.twig
 * - field--field-foo.html.twig
 * - field--text-with-summary.html.twig
 * - field.html.twig
 *
 * Available variables:
 * - attributes: HTML attributes for the containing element.
 * - label_hidden: Whether to show the field label or not.
 * - title_attributes: HTML attributes for the title.
 * - label: The label for the field.
 * - multiple: TRUE if a field can contain multiple items.
 * - items: List of all the field items. Each item contains:
 *   - attributes: List of HTML attributes for each item.
 *   - content: The field item's content.
 * - entity_type: The entity type to which the field belongs.
 * - field_name: The name of the field.
 * - field_type: The type of the field.
 * - label_display: The display settings for the label.
 *
 *
 * @see template_preprocess_field()
 */
#}
{%
  set classes = [
    'field',
    'field--name-' ~ field_name|clean_class,
    'field--type-' ~ field_type|clean_class,
    'field--label-' ~ label_display,
  ]
%}
{%
  set title_classes = [
    'field__label',
    label_display == 'visually_hidden' ? 'visually-hidden',
  ]
%}
    <div style="background: [field_button_container_color]; ">
        {% for item in items %}
            {{ item.content }}
        {% endfor %}
    </div>

```

paragraph.html.twig

```
{#
/**
 * @file
 * Default theme implementation to display a paragraph.
 *
 * Available variables:
 * - paragraph: Full paragraph entity.
 *   Only method names starting with "get", "has", or "is" and a few common
 *   methods such as "id", "label", and "bundle" are available. For example:
 *   - paragraph.getCreatedTime() will return the paragraph creation timestamp.
 *   - paragraph.id(): The paragraph ID.
 *   - paragraph.bundle(): The type of the paragraph, for example, "image" or "text".
 *   - paragraph.getOwnerId(): The user ID of the paragraph author.
 *   See Drupal\paragraphs\Entity\Paragraph for a full list of public properties
 *   and methods for the paragraph object.
 * - content: All paragraph items. Use {{ content }} to print them all,
 *   or print a subset such as {{ content.field_example }}. Use
 *   {{ content|without('field_example') }} to temporarily suppress the printing
 *   of a given child element.
 * - attributes: HTML attributes for the containing element.
 *   The attributes.class element may contain one or more of the following
 *   classes:
 *   - paragraphs: The current template type (also known as a "theming hook").
 *   - paragraphs--type-[type]: The current paragraphs type. For example, if the paragraph is an
 *     "Image" it would result in "paragraphs--type--image". Note that the machine
 *     name will often be in a short form of the human readable label.
 *   - paragraphs--view-mode--[view_mode]: The View Mode of the paragraph; for example, a
 *     preview would result in: "paragraphs--view-mode--preview", and
 *     default: "paragraphs--view-mode--default".
 * - view_mode: View mode; for example, "preview" or "full".
 * - logged_in: Flag for authenticated user status. Will be true when the
 *   current user is a logged-in member.
 * - is_admin: Flag for admin user status. Will be true when the current user
 *   is an administrator.
 *
 * @see template_preprocess_paragraph()
 *
 * @ingroup themeable
 */
#}
{%
  set classes = [
    'paragraph',
    'paragraph--type--' ~ paragraph.bundle|clean_class,
    view_mode ? 'paragraph--view-mode--' ~ view_mode|clean_class,
    not paragraph.isPublished() ? 'paragraph--unpublished'
  ]
%}
{% block paragraph %}
    {% block content %}
     <div class="Buttons">
        <button type="button" class="btn btn-primary">Primary</button>
     </div>
   {% endblock %}
{% endblock paragraph %}

```

How do I get the field value `field_button_container_color` (see screenshot) from the outer paragraph type `sidebar_button_repeater` and display its value specifically in the template `field--paragraph--sidebar-button-repeater.html.twig` to set the background color of a div?

```

<div style="background: {{ bgcolor }} ">
*[content]*
<div>

```

See 3rd screenshot for goal output.

For prepreocess code purposes let's say my theme name is `mytheme`.

Hoping to use something like IgorAgatti suggested in comments below but can't get it to work

```
function mytheme_preprocess_sidebar_button_repeater(array &$variables) {
  $bgcolor = $variables['content']['field_button_container_color'];
}

```

and simply add `{{ bgcolor }}` to `field--paragraph--sidebar-button-repeater.html.twig`

I also tried:

```
function mytheme_preprocess_paragraph(&$variables) {

  $paragraph = $variables['paragraph'];

  if ($paragraph->getType() === 'sidebar_button_repeater') {
    if (!$paragraph->field_button_container_color->isEmpty()) {

      $variables['bgcolor'] = $paragraph->get('field_button_container_color')->first()->getValue();
    }
  }
}

```

...with no success. (inspired by Retrieving value of paragraph type with entity reference revision through preprocessor)

I believe the issue may be specific to actually rendering the value in a **field** template.

Thanks

Paragraph Type Structure   Goal Output

# Answer
You can use the paragraph preprocess to alter the array of field\_paragraph\_inner

so it would be something like (untested code)

```
funcion hook_preprocess_field_paragraph_outer(array &$variables) {
  $field_bg = $variables['content']['field_bg'];

  $variables['content']['field_paragraph_inner']['field_bg_copy'] = $field_bg;
}

```

And you could use it in the field\_inner\_paragraph twig by just referencing `{{ field_bg_copy }}`
> 0 votes

---
Tags: hooks, paragraphs
---


# Question
Title: How to get $form_state->getUserInput() ( i.e, what the user entered in the input ) in each inline entity form and not only in the first one?
I use the Inline Entity Form module to build nested multiple forms. I have a **design** form in which there is an inline form - **garment**. And inside the garment form, there is a product field.

In the `hook_inline_entity_form_entity_form_alter()` I get `$field_product_user_input`

```
$field_product_user_input = $form_state->getUserInput()['field_design']['form']['inline_entity_form']['entities']['0']['form']['field_garment']['form']['inline_entity_form']['entities']['0']['form']['field_product']['0']['target_id'];

```

And I get what I need. But when I add a second inline entity form in the design, it gets the first garment's field value. This occurs because the second form has a key of **'1**' in the 'entities' array, while the code above uses **'0'** for the first form.

`$form_state->getUserInput()` show this result:

```
result = [
  'field_design' => [
    'form' => [
      'inline_entity_form' => [
        'entities' => [
          '0' => [
            'form' => [
              'field_garment' => [
                'form' => [
                  'inline_entity_form' => [
                    'entities' => [
                      '0' => [...],
                      '1' => [...] // new garment
                    ],
                  ],
                ],
              ],
            ],
          ],
        ],
      ],
    ],
  ],
];

```

# Answer
1. Use `$form_state->getUserInput()['_triggering_element_name']`
2. Using such PHP functions as: `strpos()`, `str_replace()` and `explode()` build an array of parents from what is in `$form_state->getUserInput()['_triggering_element_name']`
3. Use `NestedArray::getValue()`

Example:

```
if ($triggering_element_name = $form_state->getUserInput()['_triggering_element_name']) {
  if (strpos($triggering_element_name, '[field_product][0][target_id]') !== FALSE) {
    $triggering_element_name = str_replace(']', '', $triggering_element_name);
    $parents = explode('[', $triggering_element_name);
    if ($field_product = NestedArray::getValue($form_state->getUserInput(), $parents)) {
      $entity_product_id = EntityAutocomplete::extractEntityIdFromAutocompleteInput($field_product);
    }
  }
}

```
> 0 votes

---
Tags: entities, forms, 9
---


title: Hide date field on taxonomy page

text:
# Question
Title: Hide date field on taxonomy page
How do I hide this date field on this page? The page is a taxonomy term, not a node.

Under Manage Display, I've set Taxonomy Post Date to "Visually Hidden" but it persists.

# Answer
You only hid the field *label*. To hide the field entirely, drag the field to the "disabled" section.
> 1 votes

---
Tags: taxonomy-terms
---


title: Remove a block in preprocess

text:
# Question
Title: Remove a block in preprocess
I'm working on a Drupal 6 site made by other people, and I need to remove some block on the homepage for my language only.

I'm trying to use a Context and, by use of `hook_context_init()`, check if the context is active and remove the undesired blocks.

But i have a problem: How can I remove block in a hook function?

I hope my question is clear.

I don't want to hide the blocks with CSS because of the dirty markup..

\[RESOLVED\] I did a preprocess like:

```
function wfp_homepage_context_preprocess_block(&$vars, $hook) {
    $to_delete = array('block_delta_1', 'block_delta_2')

    if(in_array($vars['block']->delta , $to_delete)){
        $vars['template_files'][0] = 'block-empty';
    }
}

```

and i add an empty block-empty.tpl.php in my theme.

# Answer
> 3 votes
\[SOLVED\] I did a preprocess like:

```
function module_preprocess_block(&$vars, $hook) {
    $to_delete = array('block_delta_1', 'block_delta_2')
    if(in_array($vars['block']->delta , $to_delete)){
        $vars['template_files'][0] = 'block-empty';
    }
    }

```

and i add an empty block-empty.tpl.php in my theme.

# Answer
> 3 votes
You can use `hook_page_alter()` to do this. For example, if you wanted to remove the system navigation block from the "sidebar\_first" region, you would do something like this:

```
function MYMODULE_page_alter(&$page) {
  if ($my_condition) {
    $region_name = 'sidebar_first';
    $block_name = 'system_navigation';

    if (isset($page[$region_name][$block_name])) {
      $page[$region_name][$block_name]['#access'] = FALSE;
    }
  }
}

```

# Answer
> 0 votes
The hook you're looking for is `hook_block_view_alter()`, or it's delta cousin.

You'd check against `$module['delta']` to see if it's the block you care about, and then unset the subject and content of `$block`.

# Answer
> 0 votes
There doesn't seem to be an easy way to do this in D6. You if you are using the i18n internationalization module, you could define your paths, that are prepended with your language code, as exceptons in the block config menu. so something like es/\* for spanish.

Haven't tested myself, just a thought.

# Answer
> 0 votes
from Drupal8, an example of not displaying 2 blocks on 404 page:

```
 //exemple of condition
 $route_name = \Drupal::request()->attributes->get('_route');
 if ('system.404' === $route_name) {
    $region_name = 'content';
    $block_names = ['oneBlockID', 'andAnother'];
    foreach ($block_names as $block_name)
    if (isset($variables['page'][$region_name][$block_name])) {
      $variables['page'][$region_name][$block_name]['#access'] = FALSE;
    }
  }

```

---
Tags: 6, hooks, blocks
---


title: Hide block on 404 (not found) page

text:
# Question
Title: Hide block on 404 (not found) page
SITUATION:

* A View page displays all "items" that have a certain "code".
* The code is passed via a contextual filter, e.g. `/items/17`, where 17 is the code.
* A user might try to guess a code by typing it in, e.g. `/items/345`.
* When the View is empty (i.e. the code is bogus), a not-found exception is raised as follows:

```
function mymodule_views_pre_render(\Drupal\views\ViewExecutable $view) {
  if ($view->current_display == 'page_machine_name' && empty($view->result)) {
    throw new \Symfony\Component\HttpKernel\Exception\NotFoundHttpException();
  }
}

```
* There is a menu included as a block that's displayed at the top of the View page.
* The menu block configuration restricts the block to pages with paths `/items/*`.

PROBLEM:

The menu also appears on the 404 page, since that page retains the bogus path `/items/345`. How can I exclude the menu block from the 404 page?

NOTES:

* I want to display the default 404 page rather than the view with a "not found" message as its body.
* I don't want to display the view as a block instead of as a page unless it's the only way. I already know how to solve the problem if I have to do that.
* If there were a way to say, "Include this block only on View pages" (like you can for content types), that would be ideal.
* There are actually three blocks that need to be excluded from the 404 page; I mention only one to make it simpler. The other blocks are a text block and a banner block.
* I see that a solution to this problem has been proposed for Drupal 9, but not available yet.

# Answer
Yes, the solution is not available yet in core, see https://www.drupal.org/node/2245767.

But you can use this contrib module https://www.drupal.org/project/block\_in\_page\_not\_found and negate the condition to not show the block on a 404 page:
> 5 votes

# Answer
programmatically:

```
 $route_name = \Drupal::request()->attributes->get('_route');
  if ('system.404' === $route_name) {
    $region_name = 'content';
    $block_names = ['oneBlockID', 'andAnother'];
    foreach ($block_names as $block_name)
    if (isset($variables['page'][$region_name][$block_name])) {
      $variables['page'][$region_name][$block_name]['#access'] = FALSE;
    }
  }

```
> 0 votes

---
Tags: 8, views, blocks
---


# Question
Title: How to use node context in custom block plugin to get correct revision for node and its fields?
Background information for this question can be found here: How to have a different hero image per node?

I have written a custom block that takes the data from this "hero" paragraph and renders it within the region I want using custom templates that I've defined in the module file in `hook_theme`. I am using the node context definition to get the data within the "hero" paragraph that is on the node but when I go to the revisions listing and click through them, the wrong paragraph revision is not loaded in some cases.

Example:

* Create new basic page with image 1 and save as draft
* Edit, update with image 2 and save as published
* Edit, update with image 3 and save as draft

In this scenario, if I go to the revisions listings for the node, revision 1 (that should have image 1) is showing image 2. Revisions 2 and 3 have the correct images though.

Relevant code for custom block plugin:

```
<?php

use Drupal\Core\Access\AccessResult;
use Drupal\Core\Block\BlockBase;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\Entity\EntityTypeManager;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Session\AccountInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Provides an 'Hero Block' block.
 *
 * @Block(
 *   id = "hero_block",
 *   admin_label = @Translation("Hero Block"),
 *   category = @Translation("Custom"),
 *   context_definitions = {
 *    "node" = @ContextDefinition("entity:node", label = @Translation("Node"))
 *   }
 * )
 */
class HeroBlock extends BlockBase implements ContainerFactoryPluginInterface {

  /**
   * The entity manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeManager
   */
  private $entityTypeManager;

  /**
   * @param array $configuration
   * @param string $plugin_id
   * @param mixed $plugin_definition
   * @param \Drupal\Core\Routing\RouteMatchInterface
   * @param \Drupal\Core\Entity\EntityTypeManager
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManager $entity_type_manager) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->entityTypeManager = $entity_type_manager;
  }

  /**
   * @param \Symfony\Component\DependencyInjection\ContainerInterface $container
   * @param array $configuration
   * @param string $plugin_id
   * @param mixed $plugin_definition
   *
   * @return static
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('entity_type.manager')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function defaultConfiguration() {
    return ['label_display' => FALSE];
  }

  /**
   * {@inheritDoc}
   */
  public function build() {

    $node = $this->getContextValue('node');

    if (!isset($node)
        || !isset($node->field_hero)
        || $node->field_hero->isEmpty()) {
      return [];
    }

    $heroParagraph = $node->field_hero->entity;

    if (!isset($heroParagraph)
        || $heroParagraph->field_layout->isEmpty()
        || $heroParagraph->field_hero->isEmpty()) {
      return [];
    }

    $build = [];

    $cacheable_metadata = CacheableMetadata::createFromRenderArray($build);
    $cacheable_metadata->addCacheableDependency($node);
    $cacheable_metadata->addCacheableDependency($heroParagraph);

    $media = $heroParagraph->field_hero->entity;

    if (isset($media)) {
      $cacheable_metadata->addCacheableDependency($media);

      if ($media->bundle() === 'image') {
        $this->setImageVars($build, $media);
      } else {
        $this->setVideoVars($build, $media);
      }

      if (isset($build['#media']) || isset($build['#is_video'])) {
        $build['#theme'] = $heroParagraph->field_layout->value;

        $this->setTemplateVars($build, $heroParagraph);
      }
    }

    $cacheable_metadata->applyTo($build);

    return $build;
  }

```

Obviously based on my problem, I'm assuming I'm either not loading the paragraph revisions correctly, not loading the node revisions correctly, or the context value is not correct for some reason. I'm not sure which one and I've tried a few different ways of loading the paragraph or node using `\Drupal::routeMatch()->getParameter('node_revision')` if its there instead of using `$this->getContextValue('node')` or checking the node to see if its the latest revision, default revision, or something else but can't seem to get all of the revisions to display as expected whichever way I try.

# Answer
> 0 votes
Make sure you apply cacheable metadata of all entities before returning $build:

```
use Drupal\Core\Cache\CacheableMetadata;

...

  $cacheable_metadata = CacheableMetadata::createFromRenderArray($build);

  if ($node) {
    $cacheable_metadata->addCacheableDependency($node);
  }
  if ($paragraph) {
    $cacheable_metadata->addCacheableDependency($paragraph);
  }
  if ($media) {
    $cacheable_metadata->addCacheableDependency($media);
  }

  $cacheable_metadata->applyTo($build);

  return $build;
}

```

---
Tags: entities, blocks, paragraphs, plugins
---


title: Why does this Twig code not work?

text:
# Question
Title: Why does this Twig code not work?
I've recently upgraded my Drupal 9.5 website to Drupal 10.1. Everything went smoothly except for a Display with Views that contained twig code within one of the fields to rewrite the results.

Prior to the upgrade, this code containing twig within the Views display worked.

```
<span class="field-content"><span hidden itemprop="dateCreated">{{ created | date('Y-m-d') -}}></span>Published on {{ created | date('F j, Y') }}</span>

```

Can someone tell me with the upgrade to Drupal 10.1.2 using Twig 3.x why this code no longer works? Can Twig 3.x code still be used as I have described it?

# Answer
To answer my question:

With the upgrade to Drupal 10.1,Twig 3.x treats unix timestamps differently. Instead of using the twig field {{ created }}, use the raw value {{ created\__raw }} followed by the piped date format you want to display. Thus :

`{{ created__raw | date('F j, Y') }}`
> 0 votes

---
Tags: views, 10
---


# Question
Title: How to share a variable between several preprocess functions in dot theme file
I retrieve config settings that are used in two different regions. How can I get the setting once and then pass it to two different hooks?

Now I get the setting in each hook and it seems to be not quite DRY.

```
function te23_preprocess_region__navbar(&$variables) {

  $general_info = \Drupal::config('te.settings')->get('general_info');
  $variables['email'] = \Drupal::service('te.helper_functions')->render_email($general_info['email']);
  $variables['tel_link'] = \Drupal::service('te.helper_functions')->render_phone_number($general_info['phone_number']);

}

function te23_preprocess_region__footer(&$variables) {
  $general_info = \Drupal::config('te.settings')->get('general_info');
  $reviews = \Drupal::config('te.settings')->get('reviews');
  $variables['reviews'] = $reviews;
  $variables['address'] = $general_info['address'];
  $variables['email'] = \Drupal::service('te.helper_functions')->render_email($general_info['email']);
  $variables['tel_link'] = \Drupal::service('te.helper_functions')->render_phone_number($general_info['phone_number']);

}

```

# Answer
In general, hooks are not connected and don't share variables. In this case, however, both hooks are for the same base hook, so you can run the preprocess hook for the base hook `mymodule_preprecess_region()` and handle both regions, check `$variables['region']`, with DRY.
> 0 votes

---
Tags: hooks
---


title: Overriding core Drush command classes

text:
# Question
Title: Overriding core Drush command classes
I want to add some info to the Drush status report, `drush core:status`.

Does anyone know a method to do this?

I am thinking that if there is an alter service for Drush service info, I can change the class from `drush/src/Commands/core/StatusCommands.php` to my own class that overrides it, and then overriding the `status()` function within that class., however I'm unsure of how to alter Drush service info. Can anyone provide assistance?

# Answer
> 2 votes
Your commandfile should implement the Drush replace hook https://github.com/consolidation/annotated-command#replace-command-hook

---
Tags: drush
---


# Question
Title: How do I set the title tag for the maintenance page?
I need to change the default title tag for the maintenance page, which currently is "Site under maintenance | \[sitename\]".

I tried to set `$variables['head_title']` in `hook_preprocess_maintenance_page()` but it doesn't work.

Also I think it can be set in `hook_preprocess_html()`, but I don't know how to check the served page is the maintenance page.

How can I achieve this?

# Answer
> 2 votes
`TEMPLATE_preprocess_maintenance_page` changes only variables for maintenance-page.html.twig. But `<title>` is outputted in html.html.twig, so you have to choose another preprocessor `template_preprocess_html`. So you can use this code(don't forget to clean cache after it):

```
function mytheme_preprocess_html(&$variables) {
  $maintenance_mode = \Drupal::state()->get('system.maintenance_mode');
  if (!empty($maintenance_mode)) {
    $variables['head_title'] = (string)t('My Custom Maintenance Title');
  }
}

```

# Answer
> 0 votes
To change this message, you can go Adm -\> Config -\> Maintenance page and write you own message.

If you really want do this in a preprocess function:

```
function TEMPLATE_preprocess_maintenance_page(&$variables) {
  $variables['head_title'] = "A custom var that YOU going to use in maintenance-page.html.twig";
  $variables['title'] = "Default var used to display title message 'Site under maintenance' ";
}

```

Or you can even override `maintenance-page.html.twig` file to put your own message, but its not the best option.

# Answer
> 0 votes
On Drupal 9 with a subtheme from Bootstrap 5, I used this function to change the head title and the page title.

```
/**
 * Implements theme_preprocess_html().
 */
function TEMPLATE_preprocess_html(&$variables) {
  $maintenance_mode = \Drupal::state()->get('system.maintenance_mode');
  if (!empty($maintenance_mode)) {
    $title = t('My Custom Maintenance Title');
    $variables['head_title']['title'] = $variables['page']['#title'] = $title;
  }
}

```

# Answer
> 0 votes
If you don't want to write php code,you can try this↓

Since the maintenance setting page(/admin/config/development/maintenance) supports JS, it may be possible to solve this indirectly by adding the following code

```
<script type="text/javascript">
  document.title="your custom title"
</script>

```

# Answer
> -2 votes
If you have access to the backend, you can modify the string directly for a temporary change. Change `/var/www/html/` to the location of your install and other strings to fit your needs.

1. Login with SSH. `ssh root@yourdrupalsite.com`
2. Edit the file `/var/www/html/includes/common.inc` with your favorite text editor and replace `Site under maintenance` with your new message. You could also use sed. `sed -i 's/Site under maintenance/Your new title here/' /var/www/html/includes/common.inc`
3. Clear the cache. `cd /var/www/html/ && drush cc all`

This will be overwritten after an update to Drupal Core.

---
Tags: theming, 8, maintenance-mode
---


title: How do I theme a modal popup?

text:
# Question
Title: How do I theme a modal popup?
How can I style Drupal 8 modal window to achieve Instagram style and behaviour?

I'm creating modal through extending ControllerBase class, thus have full control of content. However I can't figure it out how to control outer DIV with ui-dialog classes.

```
class CustomModalController extends ControllerBase {

  public function modal($nid) {

    $options = [
      'dialogClass' => 'popup-dialog-class',
      'width' => 'auto',
      'height' => 'auto',
    ];
    $response = new AjaxResponse();
    $response->addCommand(new OpenModalDialogCommand(t('Modal title'), $html, $options));

    return $response;
  }

}

```

# Answer
> 0 votes
Have you tried this?

On your custom module, add a file

> custom\_module.module

If you already have that file, edit it, and add this

```
  function custom_module_theme() {
  return array(
    'twig-template-name' => array (
      'variables' => array(
        'eg_var' => array()
      )
    )
  );
}

function custom_module_preprocess_page(&$variables) {
  $variables['#attached']['library'][] = 'custom_module/custom-lib';
}

```

Inside the "variables" add what you need (array, text etc), it is possible to add more than one, separated by comma.

If you need to add library, css or JS only for your module, add the last function.

If you added the last function, you need to match the "custom-lib" with your libraries file (inside your custom\_module folder), like this

```
custom-lib:
  js:
    src/js/scripts.js: {}
  dependencies:
    - system/admin
    - core/jquery
    - core/drupal

```

Inside your custom\_module folder, create a folder called "templates", inside that folder create a twig file, same name you have defined on function "module\_theme" after the "return array"

> twig-template-name.html.twig

Inside this file is where you will be able to add HTML and get the results from your controller.

Inside your controller file you should return values like this

```
$returnVal = array (
        '#theme' => 'twig-template-name',
        '#title' => 'Some title',
        '#eg_var' => $response,
    );

return $returnVal;

```

With this approach it is possible to theme a modal with its own css, js and libraries.

If for some reason you need to pass some values to JS (drupal settings) it is possible to, just add this block after "'#eg\_var' =\> $response,"

```
'#attached' => array(
            'drupalSettings' => array('custom_module' => $response),
        ),

```

Inside the twig file, call the variable you have defined on .module file and you will be able to access all values you need.

```
{{ eg_var }}

```

---
Tags: 8, theming, modal-dialogs
---


# Question
Title: How can I display translated content by language?
I have a view with multiple displays, each configured as follows.

**Display 1: Articles**

* FILTER CRITERIA:
    + Content: Published (= Yes)
    + Content: Content type (= Article)
* PAGE SETTINGS:
    + Path: /articles/insights

**Display 2: Page**

* FILTER CRITERIA:
    + Content: Published (= Yes)
    + Content: Content type (= Article)
    + Content: Page Category (= Glossary)
* PAGE SETTINGS:
    + Path: /articles/glossary

**Display 3: A-F**

* FILTER CRITERIA:
    + Content: Published (= Yes)
    + Content: Content type (= Article)
    + Content: Page Category (= Glossary)
    + Content: Subtitle (regex ^\[A-Fa-f\].\*$)
* BLOCK SETTINGS:
    + Block name: None
    + Block category: Lists (Views)
    + Allow settings: Items per page

The first display, "Articles," with the path `/articles/insights`, shows the article listing, while the second, third, and other similar displays show the Glossary of articles. The Page Category is a field called `field_page_category`, which can be selected when adding an article.

Now, I have some articles that are translated into Portuguese-Brazil (pt-br) and have the page category as Glossary. I want to display these links when I access `/pt-br/articles/glossary`. I tried creating a new display for the View with the path `/pt-br/articles/glossary`, and in the filter criteria, I added:

* Content: Translation language (= Portuguese, Brazil)
* Content revision: Translation language (= Portuguese, Brazil)

However, it still displays all the links in English. I'm unable to find a Language filter when attempting to add it.

The SQL query I received is:

```
SELECT "node_field_data"."langcode" AS "node_field_data_langcode", "node__field_subtitle"."field_subtitle_value" AS "node__field_subtitle_field_subtitle_value", "node_field_data"."nid" AS "nid"
FROM
{node_field_data} "node_field_data"
INNER JOIN {node__field_page_category} "node__field_page_category" ON node_field_data.nid = node__field_page_category.entity_id AND node__field_page_category.deleted = '0'
INNER JOIN {node_field_revision} "node_field_revision" ON node_field_data.vid = node_field_revision.vid
LEFT JOIN {node__field_subtitle} "node__field_subtitle" ON node_field_data.nid = node__field_subtitle.entity_id AND (node__field_subtitle.deleted = '0' AND node__field_subtitle.langcode = node_field_data.langcode)
WHERE ((node__field_page_category.field_page_category_value = 'Glossary')) AND (("node_field_data"."status" = '1') AND ("node_field_data"."type" IN ('article')) AND ("node_field_data"."langcode" IN ('pt-br')) AND ("node_field_revision"."langcode" IN ('pt-br')))
ORDER BY "node__field_subtitle_field_subtitle_value" ASC

```

How can I configure Drupal Views to display content in Portuguese (pt-br) when accessing the `/pt-br/articles/glossary` URL? I can't seem to find the Language filter to achieve this.

The language filters I already have are as follows:

| Title | Category |
| --- | --- |
| Delivery Language | Content |
| Original language | Content |
| Translation language | Content |
| Translation source | Content |
| Original language | Content revision |
| Original language | Content revision |
| Translation language | Content revision |
| Translation source | Content revision |

# Answer
> 1 votes
If I understand your problem, you are close of the solution.

On your view add

> Content: Translation language

And then choose

> Interface text language selected for page

Instead of choosing the language. With this option, everytime you enter the page you will get the content based on your language switcher block or URL prefix.

# Answer
> 0 votes
You don't need to create /pt-br/articles/glossary path

Drupal add language prefix automatically. Needs to add views filter criteria Content: Translation language (= current language). When user select Brazil language only Brazil articles will show.

And of course you need to add Brazil language to site settings

---
Tags: views, i18n-l10n, 9
---


title: file_url() produces no output

text:
# Question
Title: file_url() produces no output
I have a custom block, and a *block--inline-block--hero-video.html.twig* template file. The block has a *field\_video* field.

If I put `{{content.field_video[0]}}` in my theme, the output is the following (as expected).

```
<span class="file file--mime-video-mp4 file--video">
  <a href="/sites/default/files/2023-09/birdcode-intro-1280.mp4" type="video/mp4">birdcode-intro-1280.mp4</a>
</span>
<span>(5.72 MB)</span>

```

I am looking to get only `/sites/default/files/2023-09/birdcode-intro-1280.mp4`.

According to Functions in Twig templates, the following should work.

```
{{ file_url(content.field_video.entity.uri.value) }}

```

Yet, that produces `null`, like the following markup.

```
{{ file_url(content.field_video.entity.uri.value) }}
{{ file_url(content.field_video[0].entity.uri.value) }}
{{ file_url(content.field_video[0].entity.uri )}}

```

It should be noted that you can define the field display as "URL" rather than "Generic file" in the admin interface, and if you do that, then `{{content.field_video[0]}}` will show `/sites/default/files/2023-09/birdcode-intro-1280.mp4`.

Nonetheless, I would like to extract the file URL in Twig in the case the field display is a generic file.

# Answer
> 0 votes
Try:

```
file_url(content.field_video['#items'].entity.uri.value)

```

Note this does not directly support translations.

---
Tags: theming
---


# Question
Title: Remove a button from CKEditor based on the role of the current user
I have a text format which should access by user role A and the admins but I only want the admins to see the "Source code" button. User's of the role A should not see this button but they should be able to use the exact same text format. Is there a way to achieve that without defining a new text format and handling all the text format during form building and entity saving?!

# Answer
> 0 votes
I had the same problem and was able to solve it with the `hook_editor_js_settings_alter` hook.
In "editorSettings" \> "toolbar" I removed the entry for the "Source" button for my format after some logic.

---
Tags: 8, wysiwyg
---


title: Drush can't write to /tmp

text:
# Question
Title: Drush can't write to /tmp
Drush does not seem to be able to move files to the tmp folder on my local machine. Changing the tmp folder location to for instance "sites/default/files" works, but I would like to know why it doesn't work with /tmp.

I am using this script from the fontawesome module:

```
$this->fileSystem->move($path . '/fontawesome-free-' . $fontawesome_library['version'] . '-web', $this->fileSystem->getTempDirectory() . '/temp_fontawesome', FileSystemInterface::EXISTS_REPLACE);

```

and I get the error

```
The specified file '/home/username/websites/frilaering_newest/web/libraries/fontawesome/fontawesome-free-6.1.0-web' could not be moved to '/tmp/temp_fontawesome'.

```

The weird thing is that everything else seems to work - including file uploads, which uses the tmp folder - so can this be related to Drush somehow? I'm using Drush installed on the local website with composer. Everything looks fine in Drush status.

* www-data can write to /tmp
* /tmp is chmodded to 777
* .htaccess file is present in /tmp folder
* settings.local.php has "$settings\["file\_temp\_path"\] = '/tmp';"

I have tried anything - even fiddling with PrivateTmp, but the only thing that works is changing the tmp folder, which I would rather avoid.

I am using Drupal 9 with php7.3-fpm/apache2/mariaDB on latest Ubuntu

Any ideas?

# Answer
## Reason

Probably the `/tmp/temp_fontawesome` directory has already been created by the web server user `www-data`.

The permissions for `/tmp/temp_fontawesome` are probably:

```
ls -lash /tmp/temp_fontawesome
4,0K drwxrwxr-x  3 www-data www-data 4,0K sep 21 13:55

```

...which means that your user, which is running drush, is not permitted to write to `/tmp/temp_fontawesome` because `other` has no write permision `r-x`, indicated by `-` instead of `w`.

## Solution A

Change the Linux group permissions, so that your user (called for example `drupaladmin`) running drush, is allowed to write to the directory:

```
sudo chgrp -R drupaladmin /tmp/temp_fontawesome
sudo chmod g+w -R /tmp/temp_fontawesome

ls -lash /tmp/temp_fontawesome
4,0K drwxrwxr-x  3 www-data drupaladmin  4,0K sep 21 13:56

```

## Solution A (could sometimes be the other way around)

If the directory is created by drush through your user first, then www-data cannot write to it. In that case the commands would be:

```
sudo chgrp -R www-data /tmp/temp_fontawesome
sudo chmod g+w -R /tmp/temp_fontawesome

```

## Solution B

Remove the directory (drush can then create the directory with your user as the owner):

```
sudo rm -r /tmp/temp_fontawesome

```
> 0 votes

---
Tags: files, drush, 9
---


title: Why can't I disable CSS caching?

text:
# Question
Title: Why can't I disable CSS caching?
# Background

I am developing a custom theme for my Drupal 10 site. I found myself constantly flushing the cache, so I have been looking up ways to disable the cache on my local dev site. My end goal is to be able to simply refresh the page to see CSS changes. I need this in order to enable live reload at a later step.

# Problem

I am having extreme difficulty disabling the cache, despite reading multiple Drupal docs and q/a's on stack overflow and stack exchange.

# Attempts

I tried many attempts outlined below over the past day and a half and each attempt failed. I also restarted Apache service after each attempt.

## Attempt 1

I found this Drupal doc and tried the steps:

1. I disabled caching on the Admin interface. This included going to **Admin -\> Configuration -\> Development -\> Development Settings** and toggling all of the options to on.
2. When this didn't work, I went to **Admin -\> Configuration -\> Performance** and changed Caching to `<no cache>`.

## Attempt 2

I tried the solutions in the question mine was closed as a duplicate of. This question said this was due to Apache caching static files but didn't explain how to fix this. I found this second question that explained how to modify the `.htaccess` file to disable caching. I added the below config to my `.htaccess` file in my root directory:

```
<IfModule mod_rewrite.c>
  RewriteEngine on
  <FilesMatch "\.(html|htm|js|css)$">
    FileETag None
    <IfModule mod_headers.c>
      Header unset ETag
      Header set Cache-Control "max-age=0, no-cache, no-store, must-revalidate"
      Header set Pragma "no-cache"
      Header set Expires "Wed, 12 Jan 1980 05:00:00 GMT"
    </IfModule>
  </FilesMatch>
</IfModule>

```
* Made sure that my `httpd.conf` is loading mod\_rewrite
* Added EnableSendfile off to `httpd.conf`

## Attempt 3

I tried the other answer on the question used to close mine which recommended to remove `version: VERSION` from the `info.yml` file. I also read through the posted blog. I tried removing the line as it recommended but this did not work.

I read through the string of q/a's and blogs which suggested removing VERSION from the `libraries.yml` file which also didn't work.

## Attempt 4

As per a comment on my first question, I added `$settings['deployment_identifier'] = 'A1234';` to my `settings.php` file.

## Attempt 5

I followed the steps here created a `settings.local.php` file. I added the below:

```
$config['system.performance']['css']['preprocess'] = FALSE;
$config['system.performance']['js']['preprocess'] = FALSE;

$settings['cache']['bins']['render'] = 'cache.backend.null';
$settings['cache']['bins']['page'] = 'cache.backend.null';
$settings['cache']['bins']['dynamic_page_cache'] = 'cache.backend.null';

```

# Conclusion

After all of these failed attempts, I don't understand what I am missing and I really want to learn how to fix this. I am open to any possible solutions or things I haven't tried.

# Additional Info

I previously posted this question but it was closed as a duplicate and linked to a solution that doesn't even fix my issue which is pretty frustrating. Seeing that it wasn't reviewed and reopened, I decided to submit a new question with much more detail so that hopefully this one isn't simply closed.

* This is in a local development environment on my computer not an external host
* I am not using the color module which is known to cause similar issues
* Stack Exchange suggested this similar answer, but it also didn't help

# Answer
> 0 votes
For some reason, the isolated fixes didn't work for me. After many more attempts, I was finally able to find a solution that works for me, and it turned out to be a combination of most of my attempts.

1. Go to `settings.local.php` and uncomment the following. Make sure the first two options are set to false:

```
$config['system.performance']['css']['preprocess'] = FALSE;
$config['system.performance']['js']['preprocess'] = FALSE;

$settings['cache']['bins']['render'] = 'cache.backend.null';
$settings['cache']['bins']['page'] = 'cache.backend.null';
$settings['cache']['bins']['dynamic_page_cache'] = 'cache.backend.null';

```

**Note:** If this file doesn't exist, you copy & paste `example.settings.local.php` from `web/sites` into `web/sites/default` and rename it to `settings.local.php`. Once this is done, you can make the above stated changes.

2. In your `settings.php` file, uncomment the section:

```
if (file_exists($app_root . '/' . $site_path . '/settings.local.php')) {
  include $app_root . '/' . $site_path . '/settings.local.php';
}

```

Otherwise the `settings.local.php` file will not be seen or used.

3. Go to your site and navigate to the **Admin Toolbar -\> Configuration -\> Development -\> Performance**. Ensure that Aggregate CSS files and Aggregate JavaScript files are both disabled.

**Note:** I am not sure why this was needed though. For me, this did not work until I disabled these and cleared the cache manually.

4. Add the following to your `/web/.htaccess` file:

```
<IfModule mod_rewrite.c>
  RewriteEngine on
  <FilesMatch "\.(html|htm|js|css)$">
    FileETag None
    <IfModule mod_headers.c>
      Header unset ETag
      Header set Cache-Control "max-age=0, no-cache, no-store, must-revalidate"
      Header set Pragma "no-cache"
      Header set Expires "Wed, 12 Jan 1980 05:00:00 GMT"
    </IfModule>
  </FilesMatch>
</IfModule>

```

I tested removing this and it broke the refresh, so it appears that this is needed at least in Drupal 10.1.3.

# Answer
> 1 votes
It's definitely the browser as commented by @No Sssweat. Clearing the browser cache should load a new version of static CSS files. Also putting the browser in dev mode or configuring the webserver to send headers not to cache the files.

This is only Drupal-specific because Drupal is adding a query string to CSS files so they can be invalidated on code updates or a full cache clear:

```
<HTML ...>
  <head>
    <link rel="stylesheet" href="/core/.../align.module.css?xyz123" />
    ...

```

See CssCollectionRenderer::render

However, you should be able to use this for your custom theme as well, when Drupal render caching is already disabled and you are building a new page HTML structure on each request anyway. Generate a new cache-busting query string for each page:

*mytheme.theme*

```
function mytheme_preprocess_page(&$variables) {
  $cache_settings = \Drupal::service('settings')->get('cache', []);
  if (isset($cache_settings['bins']['render']) && $cache_settings['bins']['render'] == 'cache.backend.null') {
    _drupal_flush_css_js();
  }
}

```

I've included a check for the local dev settings (Attempt 5). For two reasons, (a) it needs these settings to work properly and (b) it shouldn't run in a production environment.

This is not a solution for everyone. Web designers have tools to live edit CSS files. They are, as explained at the beginning, just files.

---
Tags: theming, caching, 10
---


# Question
Title: How can I get the numeric ID for a block from within the block template or hook_preprocess_block?
How can I get the numeric ID for a block from within the block template or hook\_preprocess\_block().

By numeric ID, I mean the ID that we see in the edit link for a block. For example, mysite.com/admin/content/block/**123**

Drupal version: 10

# Answer
You can check yourself with Xdebug or Kint.

```
/**
 * Implements hook_preprocess_HOOK().
 */
function MYMODULE_preprocess_block(&$variables) {

  // Check if it's a content block.
  if ($variables['elements']['#base_plugin_id'] === 'block_content') {

    /** @var \Drupal\block_content\Entity\BlockContent $block_content */
    $block_content = $variables['content']['#block_content'];

    // Get the numeric ID.
    $id = $block_content->id();

    // Code on ...
  }
}

```
> 2 votes

---
Tags: theming, blocks, 10
---


# Question
Title: building a subtheme using stark as the base theme but getting this error in the info.yml
i keep getting this error. The error goes away when i remove the info.yml file from the subtheme. I upload the subtheme in the root theme directory. I've added the error message along with the info.yml file, libraries.yml file, and the .theme file below.

> Drupal\Core\Extension\InfoParserException: Missing required keys (name) in themes/jetsetterguide/Jetsetterguide.info.yml in Drupal\Core\Extension\InfoParserDynamic-\>parse() (line 57 of core/lib/Drupal/Core/Extension/InfoParserDynamic.php). Drupal\Core\Extension\InfoParser-\>parse() (Line: 554) Drupal\Core\Extension\ExtensionList-\>createExtensionInfo() (Line: 266) Drupal\Core\Extension\ThemeExtensionList-\>createExtensionInfo() (Line: 316) Drupal\Core\Extension\ExtensionList-\>doList() (Line: 113) Drupal\Core\Extension\ThemeExtensionList-\>doList() (Line: 282) Drupal\Core\Extension\ExtensionList-\>getList() (Line: 72) Drupal\Core\Extension\ThemeHandler-\>listInfo() (Line: 55) Drupal\Core\Theme\ThemeAccessCheck-\>checkAccess() (Line: 69) Drupal\Core\Theme\ThemeNegotiator-\>determineActiveTheme() (Line: 405) Drupal\Core\Theme\ThemeManager-\>initTheme() (Line: 96) Drupal\Core\Theme\ThemeManager-\>getActiveTheme() (Line: 75) Drupal\Core\Render\ElementInfoManager-\>getInfo() (Line: 816) Drupal\Core\Form\FormBuilder-\>prepareForm() (Line: 284) Drupal\Core\Form\FormBuilder-\>buildForm() (Line: 73) Drupal\Core\Controller\FormController-\>getContentResult() call\_user\_func\_array() (Line: 123) Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber-\>Drupal\Core\EventSubscriber{closure}() (Line: 580) Drupal\Core\Render\Renderer-\>executeInRenderContext() (Line: 124) Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber-\>wrapControllerExecutionInRenderContext() (Line: 97) Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber-\>Drupal\Core\EventSubscriber{closure}() (Line: 169) Symfony\Component\HttpKernel\HttpKernel-\>handleRaw() (Line: 81) Symfony\Component\HttpKernel\HttpKernel-\>handle() (Line: 58) Drupal\Core\StackMiddleware\Session-\>handle() (Line: 48) Drupal\Core\StackMiddleware\KernelPreHandle-\>handle() (Line: 106) Drupal\page\_cache\StackMiddleware\PageCache-\>pass() (Line: 85) Drupal\page\_cache\StackMiddleware\PageCache-\>handle() (Line: 48) Drupal\Core\StackMiddleware\ReverseProxyMiddleware-\>handle() (Line: 51) Drupal\Core\StackMiddleware\NegotiationMiddleware-\>handle() (Line: 23) Stack\StackedHttpKernel-\>handle() (Line: 718) Drupal\Core\DrupalKernel-\>handle() (Line: 19)

***Here is the info.yml file I've added:***

# Answer
> 0 votes
You need to pay attention to the details.

1. Theme machine names (name of files) need to be all lowercase.
2. Your .theme file is missing an opening `<?php` tag.
3. `Global-styling:` needs to be lowercase as well, and the line break removed.
4. In the info file everything below `regions:` needs to be indented.
5. In the info file everything below `libraries:` needs to be indented and prefixed with a `-` .

---
Tags: theming
---


# Question
Title: Why does this JavaScript once implementation not work?
```
attach: function(context, settings) {
        console.log('enter');
        var element = once('addedtocart', '#addtocart', context);
        element.on('click', function () {
            var product_id = document.getElementById("addtocart").getAttribute("value");

            var product = GetProductInfo(product_id);

            //console.log();
            //attachTitleAndButton(product);
        });

    }

```

below is my libraries.yml

```
demo-js:
  version: 1.x
  js:
    js/main.js: {}
  dependencies:
    - core/jquery
    - core/drupal
    - core/once

```

getting below error

```
Uncaught TypeError: element.on is not a function
    at Object.attach (js_O9oYlgvKhzeW6csP6ljhJ8fkoJHfailxVqOunj38cJ4.js?scope=footer&delta=0&language=en&theme=olivero&include=eJx9UUFywyAM_JAxb-hLMgJUmxQjRgK7_n3BNUnj6eQixK60syyWGLXjkiCMiWliFBlsAyla_O0Cgbuf6Dnq0FB5DJwgxNjBmPE7FwideiIq-Pglg-yScdEG5KJhs1_xGBoo1JZJJ9qQ0SmzKxPIPolPRDesHjfRRx0XciXgIDNxtiV30X5_LEZY_QTZU1SC1ZsD3v8jE_vlLyUIbGe1eYdXLAIzbYPDhXQr6pqYlxSghpOJggHW51k3Vqw5tao6VgS5L7Z-9NXkqedrkhyPV2GakV1VLE2usJK81-SmJ_JiIYMxlV0gwoT8_pe6E3CLj7fzdpzSnR-mXgceVGbEN9Q4U82uvSTmayAjioWEH215MH66JZ9Q9-YH_m0LfQ:71:165)
    at js_O9oYlgvKhzeW6csP6ljhJ8fkoJHfailxVqOunj38cJ4.js?scope=footer&delta=0&language=en&theme=olivero&include=eJx9UUFywyAM_JAxb-hLMgJUmxQjRgK7_n3BNUnj6eQixK60syyWGLXjkiCMiWliFBlsAyla_O0Cgbuf6Dnq0FB5DJwgxNjBmPE7FwideiIq-Pglg-yScdEG5KJhs1_xGBoo1JZJJ9qQ0SmzKxPIPolPRDesHjfRRx0XciXgIDNxtiV30X5_LEZY_QTZU1SC1ZsD3v8jE_vlLyUIbGe1eYdXLAIzbYPDhXQr6pqYlxSghpOJggHW51k3Vqw5tao6VgS5L7Z-9NXkqedrkhyPV2GakV1VLE2usJK81-SmJ_JiIYMxlV0gwoT8_pe6E3CLj7fzdpzSnR-mXgceVGbEN9Q4U82uvSTmayAjioWEH215MH66JZ9Q9-YH_m0LfQ:22:427
    at Array.forEach (<anonymous>)
    at Drupal.attachBehaviors (js_O9oYlgvKhzeW6csP6ljhJ8fkoJHfailxVqOunj38cJ4.js?scope=footer&delta=0&language=en&theme=olivero&include=eJx9UUFywyAM_JAxb-hLMgJUmxQjRgK7_n3BNUnj6eQixK60syyWGLXjkiCMiWliFBlsAyla_O0Cgbuf6Dnq0FB5DJwgxNjBmPE7FwideiIq-Pglg-yScdEG5KJhs1_xGBoo1JZJJ9qQ0SmzKxPIPolPRDesHjfRRx0XciXgIDNxtiV30X5_LEZY_QTZU1SC1ZsD3v8jE_vlLyUIbGe1eYdXLAIzbYPDhXQr6pqYlxSghpOJggHW51k3Vqw5tao6VgS5L7Z-9NXkqedrkhyPV2GakV1VLE2usJK81-SmJ_JiIYMxlV0gwoT8_pe6E3CLj7fzdpzSnR-mXgceVGbEN9Q4U82uvSTmayAjioWEH215MH66JZ9Q9-YH_m0LfQ:22:353)
    at HTMLUListElement.<anonymous> (js_O9oYlgvKhzeW6csP6ljhJ8fkoJHfailxVqOunj38cJ4.js?scope=footer&delta=0&language=en&theme=olivero&include=eJx9UUFywyAM_JAxb-hLMgJUmxQjRgK7_n3BNUnj6eQixK60syyWGLXjkiCMiWliFBlsAyla_O0Cgbuf6Dnq0FB5DJwgxNjBmPE7FwideiIq-Pglg-yScdEG5KJhs1_xGBoo1JZJJ9qQ0SmzKxPIPolPRDesHjfRRx0XciXgIDNxtiV30X5_LEZY_QTZU1SC1ZsD3v8jE_vlLyUIbGe1eYdXLAIzbYPDhXQr6pqYlxSghpOJggHW51k3Vqw5tao6VgS5L7Z-9NXkqedrkhyPV2GakV1VLE2usJK81-SmJ_JiIYMxlV0gwoT8_pe6E3CLj7fzdpzSnR-mXgceVGbEN9Q4U82uvSTmayAjioWEH215MH66JZ9Q9-YH_m0LfQ:60:14635)
    at Function.each (js_O9oYlgvKhzeW6csP6ljhJ8fkoJHfailxVqOunj38cJ4.js?scope=footer&delta=0&language=en&theme=olivero&include=eJx9UUFywyAM_JAxb-hLMgJUmxQjRgK7_n3BNUnj6eQixK60syyWGLXjkiCMiWliFBlsAyla_O0Cgbuf6Dnq0FB5DJwgxNjBmPE7FwideiIq-Pglg-yScdEG5KJhs1_xGBoo1JZJJ9qQ0SmzKxPIPolPRDesHjfRRx0XciXgIDNxtiV30X5_LEZY_QTZU1SC1ZsD3v8jE_vlLyUIbGe1eYdXLAIzbYPDhXQr6pqYlxSghpOJggHW51k3Vqw5tao6VgS5L7Z-9NXkqedrkhyPV2GakV1VLE2usJK81-SmJ_JiIYMxlV0gwoT8_pe6E3CLj7fzdpzSnR-mXgceVGbEN9Q4U82uvSTmayAjioWEH215MH66JZ9Q9-YH_m0LfQ:3:3129)
    at ce.fn.init.each (js_O9oYlgvKhzeW6csP6ljhJ8fkoJHfailxVqOunj38cJ4.js?scope=footer&delta=0&language=en&theme=olivero&include=eJx9UUFywyAM_JAxb-hLMgJUmxQjRgK7_n3BNUnj6eQixK60syyWGLXjkiCMiWliFBlsAyla_O0Cgbuf6Dnq0FB5DJwgxNjBmPE7FwideiIq-Pglg-yScdEG5KJhs1_xGBoo1JZJJ9qQ0SmzKxPIPolPRDesHjfRRx0XciXgIDNxtiV30X5_LEZY_QTZU1SC1ZsD3v8jE_vlLyUIbGe1eYdXLAIzbYPDhXQr6pqYlxSghpOJggHW51k3Vqw5tao6VgS5L7Z-9NXkqedrkhyPV2GakV1VLE2usJK81-SmJ_JiIYMxlV0gwoT8_pe6E3CLj7fzdpzSnR-mXgceVGbEN9Q4U82uvSTmayAjioWEH215MH66JZ9Q9-YH_m0LfQ:3:1594)
    at Drupal.AjaxCommands.insert (js_O9oYlgvKhzeW6csP6ljhJ8fkoJHfailxVqOunj38cJ4.js?scope=footer&delta=0&language=en&theme=olivero&include=eJx9UUFywyAM_JAxb-hLMgJUmxQjRgK7_n3BNUnj6eQixK60syyWGLXjkiCMiWliFBlsAyla_O0Cgbuf6Dnq0FB5DJwgxNjBmPE7FwideiIq-Pglg-yScdEG5KJhs1_xGBoo1JZJJ9qQ0SmzKxPIPolPRDesHjfRRx0XciXgIDNxtiV30X5_LEZY_QTZU1SC1ZsD3v8jE_vlLyUIbGe1eYdXLAIzbYPDhXQr6pqYlxSghpOJggHW51k3Vqw5tao6VgS5L7Z-9NXkqedrkhyPV2GakV1VLE2usJK81-SmJ_JiIYMxlV0gwoT8_pe6E3CLj7fzdpzSnR-mXgceVGbEN9Q4U82uvSTmayAjioWEH215MH66JZ9Q9-YH_m0LfQ:60:14565)
    at js_O9oYlgvKhzeW6csP6ljhJ8fkoJHfailxVqOunj38cJ4.js?scope=footer&delta=0&language=en&theme=olivero&include=eJx9UUFywyAM_JAxb-hLMgJUmxQjRgK7_n3BNUnj6eQixK60syyWGLXjkiCMiWliFBlsAyla_O0Cgbuf6Dnq0FB5DJwgxNjBmPE7FwideiIq-Pglg-yScdEG5KJhs1_xGBoo1JZJJ9qQ0SmzKxPIPolPRDesHjfRRx0XciXgIDNxtiV30X5_LEZY_QTZU1SC1ZsD3v8jE_vlLyUIbGe1eYdXLAIzbYPDhXQr6pqYlxSghpOJggHW51k3Vqw5tao6VgS5L7Z-9NXkqedrkhyPV2GakV1VLE2usJK81-SmJ_JiIYMxlV0gwoT8_pe6E3CLj7fzdpzSnR-mXgceVGbEN9Q4U82uvSTmayAjioWEH215MH66JZ9Q9-YH_m0LfQ:60:11020

```

# Answer
Below code is working for me

```
if (once('addedtocart', '#addtocart', context).length) {
  $('#addtocart').on('click', function () {
    var product_id = document.getElementById("addtocart").getAttribute("value");
    var product = GetProductInfo(product_id);
  });
}

```
> 2 votes

# Answer
The new `once()` function from the new v10 `core/once` library always returns an array of elements (even if the selector matches only a single element). And vanilla JS arrays don't have a `.on()` function.

So either process the array in a loop

```
let manyElements = once('addedtocart', '#addtocart', context);
manyElements.forEach(ele => ele.doSomething())

```

or just shift the first element from the resulting array
(use the null-safe `?.` operator to prevent errors if shifting from an empty array)

```
let singleElement = once('addedtocart', '#addtocart', context).shift();
singleElement?.doSomething()

```

If you need to run a jQuery-specific function, wrap the result of `once()` into a jQuery object.

```
let manyElements = once('addedtocart', '#addtocart', context);
$(manyElements).jQuerySomething();

```
> 4 votes

# Answer
jQuery Once was deprecated in Drupal 9 and removed from Drupal 10. The change record includes a conversion guide.
> 3 votes

---
Tags: javascript, 10
---


# Question
Title: How to customize the add-to-cart form using hook_form_alter?
How can add-to-cart form be customized using hook\_form\_alter. Or better yet can layouts like display suite or panels be applied to the add to cart form using hook\_form\_alter? I have custom line item types that I would like to show using some kind add\_to\_cart form regions in 2 or 3 stacked columns.

# Answer
> 1 votes
You can use this snippet to customize the add to cart form:

```
/**
 * Implements hook_form_alter()
 */
function MYMODULE_form_alter(&$form, &$form_state, $form_id) {
  if (strpos($form_id, 'commerce_cart_add_to_cart_form_') === 0) {
    // Your form modifications go here.
  }
}

```

The `$form_id` changes based on the product that is in it, so you have to check for the string at the beginning of the `$form_id` variable.

You can theme it and/or change markup in the form like you would a regular form.

# Answer
> 0 votes
For future reference better solution is there:

```
function wallsociety_form_commerce_order_item_add_to_cart_form_alter(&$form, &$form_state, $form_id) {
 if ($form_state->getBuildInfo()['callback_object'] instanceof \Drupal\commerce_cart\Form\AddToCartFormInterface) {
   dsm($form);
 }
}

```

I chaged to hook `commerce_order_item_add_to_cart` as mentioned not working. People find this answear when searching for Drupal 9/10/11 Source: https://www.drupal.org/project/commerce/issues/2933154#comment-13885788

---
Tags: commerce, forms
---


# Question
Title: Get the view object in a custom block plugin
In Drupal 10, I want to create a custom block plugin. Blocks instances of this new block type would be placed in a region on a View page.

How can I gain access to the View object from a programmatic block? I had thought perhaps adding a ContextDefinition in the block annotation, but I don't see that View is a possible option.

In the block I'd like to have access to the $view-\>result array, after the View has been executed.

Any thoughts?

# Answer
To Get View object in custom block plugin you can follow this snippet code: (Drupal 9/10)

```
use Drupal\views\Views;

// Get current route object.
  $route = \Drupal::routeMatch()->getRouteObject();
  if ($route) {
    // Get view id & display id from current route.
    $view_id = $route->getDefault('view_id');
    $display_id = $route->getDefault('display_id');
    if (!empty($view_id) && !empty($display_id)) {
      // Get the view by id.
      $view = Views::getView($view_id);
      if ($view) {
        // Set display id.
        $view->setDisplay($display_id);
        // Run execute() to get result count.
        $view->execute();
        // Get view result count.
        $result_count = $view->total_rows;
      }
    }
  }

```

Note: Don't skip $view-\>execute() otherwise result\_count 'll be render null despite of having value

If the code works fine the can do code optimization, like instead of calling directly APIs like below: can use dependency injection

```
\Drupal::routeMatch()->getRouteObject();

```

Reference link on dependency injection in a plugin (block)
> 2 votes

# Answer
I am not sure I follow your question entirely, but when you make a views page, you should have all of the regions all of your other pages have, you just put your block in there like you would any other page -- unless you have changed the theme for that page and then you need to look to see what regions that theme is providing.
> 0 votes

---
Tags: views, blocks, 10
---


title: Modal does not handle errors on login

text:
# Question
Title: Modal does not handle errors on login
I have used 'use-ajax' class to render login form in a modal. I want to handle validation errors on same modal without closing it. On successful login it is redirecting correctly, but when an error occurs it closes modal and redirecting to login page i.e user/login and displaying errors on that page. I tried to use ajax callback to display error on modal itself by altering the form which is working. But, it is giving me drupal ajax error. Here is my code :

```
$form['#prefix'] = '<div id="modal-form">';
$form['#suffix'] = '</div>';
$form['status_messages'] = [
    '#type' => 'status_messages',
    '#weight' => -10,
];
//$form['actions']['submit']['#limit_validation_errors'] = array();
$form['actions']['submit']['#ajax'] = array(
    'callback' => 'setMessage',
    'wrapper' => 'modal-form',
);

```

---

```
function setMessage(&$form, \Drupal\Core\Form\FormStateInterface $form_state) {

    $response = new AjaxResponse();

    if ($form_state->hasAnyErrors()) {
        $response->addCommand(new ReplaceCommand('#modal-form', $form));
    }
    else {
        $command = new CloseModalDialogCommand('#modal-form', FALSE);
        $response->addCommand($command);
    }
    return $response;

}

```

The above code giving me session id also but due to drupal ajax error it does not redirect on success by closing modal.

# Answer
I have resolved it by commenting redirection code from hook\_login and added redirection code related changes in ajax callback function itself. Here is my code.

```
function setMessage(&$form, \Drupal\Core\Form\FormStateInterface $form_state) {

     $response = new AjaxResponse();
     $current= \Drupal::currentUser();
     if ($form_state->hasAnyErrors()) {
         $response->addCommand(new ReplaceCommand('#modal-form', $form));

     }
     else if (!$current->id()) {
         $response->addCommand(new ReplaceCommand('#modal-form', $form));
     }
     else {
         $command = new RedirectCommand(' ');

         return $response->addCommand($command);
     }
     return $response;
}

```
> 0 votes

# Answer
Here is snippet code to display the error message in popup: (Core: Login form)

```
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\EventSubscriber\MainContentViewSubscriber;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\ReplaceCommand;
use Drupal\Core\Ajax\CloseModalDialogCommand;
use Drupal\Core\Ajax\RedirectCommand;

function login_popup_form_alter(array &$form, FormStateInterface $form_state, $form_id) {
  if ($form_id == 'user_login_form') {
    // Check if the current request is for an Ajax modal/dialog.
    if (login_popup_is_dialog() == TRUE) {
      // Add a wrapper around the form so that we can replace it.
      $form['#prefix'] = '<div id="modal_user_login_form">';
      $form['#suffix'] = '</div>';
      // The status messages that will contain any form errors.
      $form['status_messages'] = [
        '#type' => 'status_messages',
        '#weight' => -10,
      ];
      // Add form validation to the submit btn & make it Ajax.
      $form['actions']['submit']['#validate'] = $form['#validate'];
      $form['actions']['submit']['#attributes']['class'][] = 'use-ajax';
      $form['actions']['submit']['#ajax'] = [
        'callback' => 'login_popup_submit_modal_form_ajax',
        'event' => 'click',
      ];
    }
  }
}

/**
 * AJAX callback that displays the form errors or redirects to page.
 */
function login_popup_submit_modal_form_ajax(array $form, FormStateInterface $form_state) {
  $response = new AjaxResponse();
  // If there are any form errors, re-display the form.
  if ($form_state->hasAnyErrors()) {
    $response->addCommand(new ReplaceCommand('#modal_user_login_form', $form));
  }
  else {
    // On successfully form submission close dialog & redirect to the user page.
    $response->addCommand(new CloseModalDialogCommand());
    $uid = \Drupal::currentUser()->id();
    $redircet_path = Url::fromRoute('entity.user.canonical', ['user' => $uid])->toString();
    $response->addCommand(new RedirectCommand($redircet_path));
  }

  return $response;
}

* Is the current request for an Ajax modal/dialog.
 *
 * @return bool
 *   TRUE if the current request is for an Ajax modal/dialog.
 */
function login_popup_is_dialog() {
  $wrapper_format = \Drupal::request()->query
    ->get(MainContentViewSubscriber::WRAPPER_FORMAT);
  return (in_array($wrapper_format, [
    'drupal_ajax',
    'drupal_modal',
    'drupal_dialog',
    'drupal_dialog.off_canvas',
  ])) ? TRUE : FALSE;
}

```

**Note:**

**#1** This below code is required so that the core(login) form validation fire in popup,otherwise inbuilt validation of core(login) form will not fire/display in popup.

```
$form['actions']['submit']['#validate'] = $form['#validate'];

```

**Explanation:** Any core/contrib(inbuilt) form that we want to just display in popup, but face problem that validation error not display in popup:

To reuse form validation instead of writing duplicate code, solution behind this problem:

Get the validation definition of core/contrib(login) form in hook\_form\_alter \> set the validation definition in the "#validate" variable in submit handler of popup form.

**#2** login\_popup is module name, can update "login\_popup" as per your module name.

**#3** login\_popup\_is\_dialog : Custom function used to determine whether form is open in modal or not, if form is not opened is modal then is no point to add this code.
> 0 votes

---
Tags: 8, ajax, modal-dialogs
---


# Question
Title: How do I display different "No results behavior" based on exposed filter results and total results?
e.g. A view for job postings has an exposed filter to search by title.

1. I want to show a "No results behavior" if there aren't any jobs at all `"There are no postings at this time. Please check back later."`
2. I also want to show different text if their search returned no results, but there are still postings available. It's just their search didn't match anything. `"Sorry, there are no results matching your search criteria."`

It appears that I can only do one or the other.

# Answer
> 4 votes
You could easily adapt the `views-view.tpl.php` to your specific view, eg, `views-view--VIEWNAME.tpl.php` and change up the portion dealing with no results...

```
<?php if ($rows): ?>
  <div class="view-content">
    <?php print $rows; ?>
  </div>
<?php elseif ($empty): ?>
  <div class="view-empty">
    <?php print $empty; ?>
  </div>
<?php endif; ?>

```

...with something along the lines of...

```
<?php if ($rows): ?>
  <div class="view-content">
    <?php print $rows; ?>
  </div>
<?php elseif ($empty): ?>
  <div class="view-empty">
    <?php if (count($_GET)>1): ?>
      Sorry, there are no results matching your search criteria.  Perhaps with other filters you may find some.
    <?php else: ?>
      There are no postings at this time. Please check back later.
    <?php endif; ?>
  </div>
<?php endif; ?>

```

...with just some really simple logic based upon parameters Views uses for the exposed filters (eg, if more than `?q=PATH` is sent it will have more than just 1 in `$_GET`).

Now if you want to get fancier than this you may want to investigate one of the Views preprocess hooks and actually change up the `$empty` variable and not put a lot of logic in the template.

If that's the case you could go further and re-run the View via views\_get\_view\_result() without any filters and if it had any results, actually return your desired `Sorry, there are no results matching your search criteria.` (You could do this in this template file but I really try to keep lots of deep logic outside of them)

(Is there any way to dynamically add a CSS class selector to a view with submitted exposed filters? has some more code you might be able to re-use here as well)

# Answer
> 0 votes
Snippet code to display different "No results behaviour" based on exposed filter results and total results:

```
/**
 * Implements hook_preprocess_views_view__HOOK() for job posting view.
 */
function nkf_preprocess_views_view__job_posting(&$variables) {
  $view = $variables['view'];
  if ($view->current_display == 'page_1') {
    $result_count = $view->total_rows;
    $exposedInput = $view->getExposedInput();
    // Set the no result behaviour if job_type filter selected.
    if (!empty($exposedInput['job_type']) && $result_count == null) {
      $variables['empty'] = t('There are no postings at this time. Please check back later.');
    }
    elseif ($result_count == null) {
      // Set the no result behaviour if job_type filter not selected.
      $variables['empty'] = t('Sorry, there are no results matching your search criteria.');
    }
  }
}

```

**Note:** job\_posting denotes the machine name of view, nkf denotes either module or theme name depends upon working in .module/.theme file

**Informative tips:** The solution of this problem to use: `hook_preprocess_views_view__HOOK()` instead of using `hook_form_views_exposed_form_alter()`

Earlier I was trying to use `hook_form_views_exposed_form_alter` however I wasn't able to update the no result behaviour then came to know major basic difference between them and reach to solution.

**hook\_preprocess\_views\_view\__HOOK**: This hook 'll be use to alter the view variables (for eg: no result behaviour variable) before rendering view.

**hook\_form\_views\_exposed\_form\_alter**: This hook 'll be use to alter form definition/elements (for eg: alter exposed filter) before executing view.

---
Tags: 7, views
---


# Question
Title: How can I programmatically update an exposed filter?
I am trying to apply an exposed filter programmatically.

If filter 'a' is set to 'apple' I want to set filter 'b' to 'green'.

Using this code updates the filter. If a user sets the drop-down filter 'a' to 'apple' and clicks apply, then the drop-down filter 'b' is updated to 'green'; but the filter isn't applied. The results still show what the user had set filter 'b' to, instead of updating the results to show if filter 'b' was set to 'green'.

```
function my_module_views_pre_view(ViewExecutable $view, string $display_id, array $args) {
  if (($view->id() === 'my_view')) {
    $exposedInput = $view->getExposedInput();

    if ($exposedInput['a'] = 'apple') {
      $exposedInput['b'] = 'green';
    }

    $view->setExposedInput($exposedInput);
  }
}

```

How can I update the results, not just set the drop-down filter value?

# Answer
If you see above code there is syntax mistake use "==" operator:

```
if ($exposedInput['a'] = 'apple') {

```

Correct syntax:

```
  if ($exposedInput['a'] == 'apple') {

```

if the dependent filter field 'b' is plain text then following code 'll work fine

```
$exposedInput['b'] = 'green';

```

Note: if dependent filter field 'b' is select list type then need to set key value, not label value otherwise result 'll not render as per logic.
> 1 votes

# Answer
In addition to checking the operator in the if statement "==" vs "=", the following should work. Note, the method overrides any existing filters hence the use of array\_merge .

```
$view->setExposedInput(
  array_merge(
    $view->getExposedInput(),
    $may_custom_filters_array
  )
);

$view->pre_execute();
   $view->execute()

```

Check out:

https://www.drupal.org/forum/support/module-development-and-code-questions/2018-09-17/programmatically-set-exposed-input

https://www.drupal.org/project/drupal/issues/3013530

How can I pass the filter parameters of one view to a different view on the same page?
> 0 votes

---
Tags: 8, views
---


# Question
Title: How do I move taxonomy, content and content types?
I have a Drupal site which is throw away, but I need to move the taxonomies and content to a clean site, which I have decided to use Drupal 10.

I have the Drupal 9 database loaded into the same database server and set up in the setting.php and I need a way to get it all into the new d10 install. Migration doesn't seem to recognize my migration yml files. My migration module is on and the migrate module is on. I am wondering if they are not being recognized because it's Drupal 9 to 10 and not coming from Drupal 6 or Drupal 7. Below is one of my yml files in case I have done something wrong.

```
id: group
label: 'Migrate Group'
migration_group: custom_taxonomy
source:
  plugin: d9_taxonomy_term
  vocabulary: group
  key: migrate
destination:
  plugin: entity:taxonomy_term
process:
  vid:
    plugin: default_value
    default_value: group
  name: name
  parent:
    plugin: migration_lookup
    migration: group
    source: parent_tid
migration_dependencies:
  required: []

```

# Answer
If you have access to drush, can you use the following drush commands.

https://drushcommands.com/drush-8x/migrate/

Or you can install this module to export the taxonomy (D8 or D9 Compatible).

https://www.drupal.org/project/term\_trans\_ex\_im
> 0 votes

---
Tags: migrations, 10
---


# Question
Title: How to add Rabbit Hole to a custom content entity
We use the module Rabbit Hole for nodes and terms. Now we would like to use it also for our custom content entities. I have tried to find some information, how to add the Rabbit Hole to a custom content entity. I have found some related information, but maybe there is some manual, which would be more specific.

I have found:

# Answer
Here is an example for v 1.x.

```
<?php

namespace Drupal\my_module\Plugin\RabbitHoleEntityPlugin;

use Drupal\my_module\Plugin\RabbitHoleEntityPluginBase;

/**
 * Implements rabbit hole behavior for custom eck entity type.
 *
 * @RabbitHoleEntityPlugin(
 *   id = "rh_my_eck_type",
 *   label = @Translation("Custom ECK entity"),
 *   entityType = "custom_eck_entity_type_id"
 * )
 */
class CustomEckEntityType extends RabbitHoleEntityPluginBase {}

```

Optionally if you want allow override rh rules per each entity then implement this hook:

```
/**
 * Implements hook_entity_base_field_info().
 */
function my_module_entity_base_field_info(EntityTypeInterface $entity_type) {
  if ($entity_type->id() === 'custom_eck_entity_type_id') {
    $fields = \Drupal::service('rabbit_hole.entity_extender')
      ->getRabbitHoleFields('custom_eck_entity_type_id');
    return $fields;
  }
}

```

*Note: RH v.2.x architecture is different and other content entities should be supported of of the box. v.1 and v.2 are incompatible*
> 0 votes

---
Tags: entities, 9
---