1

I created a simple test module that adds a text banner to all nodes if a checkbox is checked in the form of the modules configuration. Currently it is working halfway as I want.

When the checkbox is checked and the configuration is exported the text banner displays on all nodes.

So far this is correct. But I don't want to have to export the configuration for the text banner to display. I want it to display immediately after checking the checkbox.

An example is in Devel. If you go to the admin area of Devel and check the box 'Display $page array' The page array displays on every node afterwards without having to export the configuration

To display a text banner on all nodes I am using hook_node_view. Then getting the checkbox value from my custom module settings.yml file.

function my_form_configy_node_view(array &$build, \Drupal\Core\Entity\EntityInterface $entity, \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display, $view_mode) {

  $config = \Drupal::config('my_form_configy.settings')->get('checkbox');

  if ($config === TRUE) {

      $build['layout_test'] = [
        '#markup' => '<h2> Extra, Extra read all about it.</h2>',
      ];
    }
}

This is my form

namespace Drupal\my_form_configy\Form;

use Drupal\Core\Database\Database;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Form\ConfigFormBase;

class MyForm extends ConfigFormBase {

  public function getFormId() {
    return 'my_form_configy_1346';
  }

  const SETTINGS = 'my_form_configy.settings';

  protected function getEditableConfigNames() {
    return [
      static::SETTINGS,
    ];
  }


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

  $config = $this->config(static::SETTINGS);

    $check = \Drupal::config('my_form_configy.settings')->get('checkbox');

    $form['checkbox'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Do you want to add the text banner to all nodes? Checking this box will add a large h2 text banner to add nodes. You must export the config and reload a node page'),
      '#default_value' => $check,
      '#weight' => '0',
    ];

    $form['#theme'] = 'my_form';
      return parent::buildForm($form, $form_state);
  }


  public function submitForm(array &$form, FormStateInterface $form_state) {
    $this->configFactory->getEditable(static::SETTINGS)
      ->set('checkbox', $form_state->getValue('checkbox'))
      ->save();
    parent::submitForm($form, $form_state);
  }


}

Devel is using the same method I am, but if you check the box 'Display $page array' the dpm feature works on nodes immediately without having to export the configuration.

function devel_page_attachments_alter(&$page) {
  if (\Drupal::currentUser()->hasPermission('access devel information') && \Drupal::config('devel.settings')->get('page_alter')) {
    dpm($page, 'page');
  }
}

I have searched for ConfigFormBase in core and contrib modules and read this. https://www.drupal.org/docs/drupal-apis/configuration-api/working-with-configuration-forms and https://www.drupal.org/docs/8/api/form-api/configformbase-with-simple-configuration-api

Update. 4k4 comment below put me in the right place. According to this post https://drupal.stackexchange.com/a/266393/58880. I needed to apply addCacheableDependency

\Drupal::service('renderer')->addCacheableDependency($variables, $config);

Since I am using hook_node_view. I changed $variables to $build

\Drupal::service('renderer')->addCacheableDependency($build, $config);

Now when I click the checkbox the value of chechbox is correct and its not coming form the config. The text banner is displayed on all nodes. My change is below.

function my_form_configy_node_view(array &$build, \Drupal\Core\Entity\EntityInterface $entity, \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display, $view_mode) {

  $config = \Drupal::config('my_form_configy.settings')->get('checkbox');
  // add the cache tag, so that the output gets invalidated when the config is saved
  \Drupal::service('renderer')->addCacheableDependency($build, $config);

I am trying to understand what this does? Where is the value of 'checkbox' being stored now. Its not in my modules settings.yml file because I have not exported the configuration yet. Is it stored in browser cache, or Drupal cache? Since I am developing I disabled all twig and drupal cache in settings.local.php with.

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

The Devel module is not using addCacheableDependency

Clicking the checkbox 'Display $page array' The dpm feature works immediately.

function devel_page_attachments_alter(&$page) {
  if (\Drupal::currentUser()->hasPermission('access devel information') && \Drupal::config('devel.settings')->get('page_alter')) {
    dpm($page, 'page');
  }
}
7
  • 3
    This could be a caching issue, see drupal.stackexchange.com/questions/294839/…
    – 4uk4
    Commented Sep 8, 2020 at 16:27
  • Thank you 4k4. It was cache. I updated my post above. I needed to add. \Drupal::service('renderer')->addCacheableDependency($build, $config); Commented Sep 8, 2020 at 20:02
  • Where is the value of 'checkbox' being stored now. Its not in my modules settings.yml file because I have not exported the configuration yet. Commented Sep 8, 2020 at 20:03
  • In the active configuration stored in the database.
    – 4uk4
    Commented Sep 8, 2020 at 20:07
  • I'm still learning. I did not know about active configuration. I looked in the database and found the table named config. Inside that I found my custom module setting file stored as a blob text. Thank for this information. Commented Sep 8, 2020 at 20:31

1 Answer 1

1

hook_ENTITY_TYPE_view() is probably the most misunderstood/misused hook in Drupal 8, mainly because it behaves differently than it did in Drupal 7 so you will find many misleading examples which no longer work in the current version of Drupal.

In short, hook_ENTITY_TYPE_view() is only called when the entity is being rendered - after the entity has been rendered, core Drupal caches the rendered entity and will use the cached version of the rendered entity.

So by design, hook_ENTITY_TYPE_view() will NOT be called again when the rendered entity is loaded from the cache. And specifically it is NOT called every time you visit that node page.

There are all sorts of other ways to do what you want. Since you're already using your own theme function it might be easiest to pass your configuration variable to the Twig template and display/don't display something in the template based on that variable. Another way would be to invalidate the cache when the form is submitted (if the configuration value has changed) so that the node(s) get re-rendered next time they're loaded.

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.