title: Add Field as Entity in Group Module

text:
# Question
Title: Add Field as Entity in Group Module
The group module is an alternative to the og module. The og module allows you to assign permissions to fields per group. I would like to be able to do the same thing with the group module. It appears that in order to do this, I need to add a field or fields as an entity in the Group module. All my searches seem to indicate that the GroupContentEnabler plugin will enable me to do this. But I can't find any clear example of how. Can someone point me to some documentation on how to go about coding this?

Follow up:

It appears that hook\_entity\_field\_access() will allow me to do what I wish to do. I found an example of it's use in the group module:

This is the code used in group.module (not gnode.module):

```
/**
 * Implements hook_entity_field_access().
 *
 * {@inheritdoc}
 *
 * @todo Move this to a form controller so we can hide the field if it has no
 *       options available to it?
 */
function group_entity_field_access($operation, FieldDefinitionInterface $field_definition, AccountInterface $account, FieldItemListInterface $items = NULL) {
  // Can't retrieve an entity from an empty item list.
  if (!isset($items)) {
    return AccessResult::neutral();
  }

  // We only care about the group_roles field when on a form.
  if ($field_definition->getName() != 'group_roles' || $operation !== 'edit') {
    return AccessResult::neutral();
  }

  **// We only care if it is attached to a group content entity.
  if ($items->getEntity()->getEntityTypeId() != 'group_content') {
    return AccessResult::neutral();
  }**

  /** @var \Drupal\group\Entity\GroupContentInterface $group_content */
  $group_content = $items->getEntity();

  // We only care if the group content entity is a group membership.
  if ($group_content->getContentPlugin()->getPluginId() != 'group_membership') {
    return AccessResult::neutral();
  }

  // Now that we know we're dealing with a group_roles field on a group
  // membership form, we need to check whether the group membership belongs to a
  // group yet. If not, we can't check for access and should always hide it.
  if (!$group = $group_content->getGroup()) {
    return AccessResult::forbidden();
  }

  // Only group administrators should be able to change the membership roles.
  return AccessResult::forbiddenIf(!$group->hasPermission('administer members', $account));
}

```

It appears that all I have to do is create a group permission, then check access to the field in question against that permission using hook\_entity\_field\_access().

My only question is with this code:

```
// We only care if the group content entity is a group membership.
  if ($group_content->getContentPlugin()->getPluginId() != 'group_membership') {
    return AccessResult::neutral();
  }

```

Let's say I create a custom field called "my\_test\_field". And, I create a group permission called "access test field". I then change above code:

```
// We only care about the the my_test_field field.
          if ($field_definition->getName() != 'my_test_field'
...
...
// Only users with 'access test field' should be able to see my_test_field.
  return AccessResult::forbiddenIf(!$group->hasPermission('access test field, $account));

```

If this field is attached to a node that is in a group, I am assuming that it is now attached to the group node entity. But what about this?:

```
 if ($group_content->getContentPlugin()->getPluginId() != 'group_membership') {

```

Is the field also now automatically a group membership? I guess I don't understand what that means in this context.

# Answer
I am not sure how you would approach this by adding the fields as entities via the `GroupContentEnabler` (that'd mean one custom plugin per field? Given a large number of fields that *might* not be the best solution). However, for an example how to implement your own custom group-content-type plugin see this answer.

Another possible approach that might be worth checking is to implement `hook_entity_field_access()` to define access checks for single fields programmatically (that's how I've solved a similar problem). See the group module's `gnode.module` file for an example how to check permissions/roles for users and add cache-tags to access results.
> 0 votes

# Answer
The solution to this problem is to load the group content from the node to which the field entity is attached.

// This field is a node entity $node = $items-\>getEntity(); $type = $node-\>bundle(); $group\_content\_types = GroupContentType::loadByContentPluginId("group\_node:$type"); $group\_content = reset($group\_contents);

This same logic also works for paragraph fields, with this additional code:

// This field is a paragraph entity $onode = $items-\>getEntity(); $otype = $onode-\>bundle(); // original type (paragraph) // Get the parent entity of the paragraph, which is a node $node = $onode-\>getParentEntity(); $type = $node-\>bundle(); // new type (node) $group\_content\_types = GroupContentType::loadByContentPluginId("group\_node:$type"); $group\_content = reset($group\_contents);
> 0 votes

---
Tags: entities, files, group
---


title: Alter contextual links

text:
# Question
Title: Alter contextual links
I'm trying to alter custom blocks contextual menu. In particular I need to remove "Configure block" and "Delete". Is there any way to achieve this?

# Answer
The correct way to alter contextual links is to use `hook_contextual_links_alter`.

In your case, it should look something like:

```
function my_module_contextual_links_alter(array &$links, $group, array $route_parameters) {
  if ($group === 'block') {
    // Hide Configure Block option.
    unset($links['entity.block.edit_form']);
  }
}

```

The contextual links are heavily cached in the browser, therefore you need to make sure that the browser session cache is cleared - `window.sessionStorage.clear();` \- source.
> 3 votes

# Answer
You can by adding this to your theme's css file.

**style.css**

```
.block-configure,
.block-contentblock-delete {
  display: none;
}

```
> -1 votes

---
Tags: 8, navigation
---


title: Display Themed 'username' in Block

text:
# Question
Title: Display Themed 'username' in Block
I am trying to display the themed `username` in a custom block.

**MyCustomBlock.php**:

```
public function build() {

  $usersData = \Drupal::service('user.data')->get('my_module');

  $usersFromQuery = [];

  foreach ($usersData as $id => $value) {
    if (some logic) {
      $usersFromQuery[] = User::load($id);
    }
  }

  $userList = \Drupal::entityTypeManager()
    ->getViewBuilder('user')
    ->viewMultiple($usersFromQuery, 'compact');

  return $userList;

}

```

This gets me all the users I need, but not the altered/themed `username` I need.

In `MYMODULE.module` I am altering the username.

I've also tried:

* `$users = User::loadMultiple($userQuery);`
* `User::load($uid)->getDisplayName()`

but the username is rendered without `hook_preprocess_username()` alters.

I think the issue is similar to needing this: https://drupal.stackexchange.com/a/278717/79805

```
$variables['userName'] = [
  '#theme' => 'username',
  '#account' => $account,
];

```

but I am unsure how to get the themed username in my block.

**How can I display the altered username in my block?**

---

Update:

Using a helper function in `MYMODULE.module` that creates the markup for the altered username, and `->setUsername()`, I am able to change the username in my custom block.

```
foreach ($usersData as $id => $value) {
  if (some logic) {
    $userItem = User::load($id);
    $userItem->setUsername(markup($id, $userItem->getUsername()));
    $usersFromQuery[] = $userItem;
  }
}

```

But is not really an answer to the question.

# Answer
> 0 votes
You invoke `hook_preprocess_username()` by rendering the template `username`. Since D8 has no longer a theme() function the only way to do this is by putting the template in `#theme` of a render array. In your case multiple times:

```
public function build() {
  $build = [];
  foreach ($usersFromQuery as $user) {
    $build[] = [
      '#theme' => 'username',
      '#account' => $user,
    ];
  }
  return $build;
}

```

---
Tags: 8, blocks
---


# Question
Title: Is there a way to run drush updb without going to maintenance mode
I have a live site which runs on drupal 8. I am using drush 8.5.3 with the installation. Whenever I run drush updb the site automatically goes to maintenance mode. Is there a way to do this without going to maintenance mode. In simple words, can I use drush updb with my site running?

# Answer
Actually, if you take a look at the drush code for updatedb command, you can find this piece of code in updateBatch() function:

```
$original_maint_mode = \Drupal::service('state')->get('system.maintenance_mode');
if (!$original_maint_mode) {
    \Drupal::service('state')->set('system.maintenance_mode', true);
    $operations[] = ['\Drush\Commands\core\UpdateDBCommands::restoreMaintMode', [false]];
}

```

For safety reasons, the drush command puts your site in maintenance mode during the update and then set it back online once it is completed. It prevents your users from accessing the website and generate possible conflicts within the database while it is updating.

There is a pretty clear explanation of this here

If you really wish to avoid the maintenance mode, though, you could run `update.php` directly from your website.
> 3 votes

# Answer
No. The critical path for `drush updb` is through:

Where `drush_update_batch()` toggles the maintenance mode state prior to processing the updates needed to be processed.

Theoretically, you could modify Drush itself or create your own Drush command that mimics the `drush_update_batch()` code without toggling maintenance mode. But a better question would be *why?* Maintenance mode is being set to prevent any problems while DB schema is being altered.
> 3 votes

---
Tags: 8, drush, maintenance-mode
---


# Question
Title: Site not working after the database update
I cloned a repo of a site to my local computer, imported the database and ran "Composer install --with-dependencies" after the installation had been done I entered the local site and it worked, then I ran "drush updb -y" and it showed a couple of errors and warnings:

```
    The following module is missing from the file system: aspambot       [warning]
bootstrap.inc:268
The following module is missing from the file system: phpmailer      [warning]
bootstrap.inc:268

```

...

```
PHP  27. include() /home/www/sites/zb/web/vendor/composer/ClassLoader.php:444
Drush command terminated abnormally due to an unrecoverable error.   [error]
Error: Interface 'Doctrine\Common\Reflection\ClassFinderInterface'
not found in
/home/www/sites/zb/web/core/lib/Drupal/Component/Annotation/Reflection/MockFileFinder.php,
line 14
The external command could not be executed due to an application     [error]
error.
PHP Fatal error:  Interface 'Doctrine\Common\Reflection\ClassFinderInterface' not found in /home/www/sites/zb/web/core/lib/Drupal/Component/Annotation/Reflection/MockFileFinder.php on line 14

```

I'm new to Drupal, so please help me get over these errors, I understand that the solution may seem straightforward to some, but I don't know what to do. Thank you!

# Answer
Add `"doctrine/common":">2.8"` under conflict in your composer file and then run `composer update`.

```
"conflict": {
    "drupal/drupal": "*",
    "doctrine/common":">2.8"
},

```

See issue: https://www.drupal.org/project/drupal/issues/2986725
> 5 votes

# Answer
Thanks for giving a link to https://www.drupal.org/project/drupal/issues/2986725, where this problem is discussed.

That issue was closed as "works as designed". If you look at the last few comments on the issue, you will see why. The problem is caused by the PHP cache. If you clear the cache (or restart PHP or reboot your computer or use PHP on a Docker container that does not have the wrong autoload data in its cache) then the problem goes away.

Clearing the cache has fewer side effects than never updating to the current version of `doctrine/common`.
> 1 votes

# Answer
I'm struggling with the same error, and had no time to dig the entire problem about Composer. But I came up with a workaround as follows:

1. Delete core and vendor folders from your Drupal root directory.

`$ rm -rf core vendor`
2. From a fresh downloaded drupal, copy core and vendor folders to your Drupal root directory.

`$ cp -R core vendor /path/to/drupal/root/directory/`

I had the problem on two servers. On one I managed to restore from an existing backup. And on the other I managed to resolve the problem with the steps above.
> -2 votes

---
Tags: 8, database, updating
---


# Question
Title: How to get the File Description on a custom field formatter?
Greetings to all of you.

This is my first question posted around here, so any suggestions are welcome on improving how to better formulate questions.

Into the matter. I have the following code in a Drupal 8 site:

```
<?php

/**
 * @file
 * Contains \Drupal\mymodule\Plugin\Field\FieldFormatter\MyModuleFormatter.
 */

namespace Drupal\mymodule\Plugin\Field\FieldFormatter;

use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Url;

/**
 * Plugin implementation of the 'mymodule' formatter.
 *
 * @FieldFormatter(
 *   id = "mymodule",
 *   label = @Translation("My Module"),
 *   field_types = {
 *     "file"
 *   }
 * )
 */

class MyModuleFormatter extends MyModuleFormatterBase {

  /**
   * {@inheritdoc}
   */
  public function viewElements(FieldItemListInterface $items, $langcode) {
    $element = array();
    $files = $this->getEntitiesToView($items, $langcode);

    /**
     * Early opt-out if the field is empty.
     */
    if (empty($files)) {
      return $elements;
    }

    foreach ($files as $delta => $file) {
      $file_uri = $file->getFileUri();

      $elements[$delta] = array(
        '#theme' => 'mymodule',
        '#files' => array(Url::fromUri(file_create_url($file_uri)));
      );
    }

    return $elements;
  }
}

```

So far so good. Everything is working.

Now, I would like to include in $elements the file description. Something like:

```
foreach ($files as $delta => $file) {
  $file_uri = $file->getFileUri();
  $file_description = <someting> // That's what is needed...

  $elements[$delta] = array(
    '#theme' => 'mymodule',
    '#files' => array(Url::fromUri(file_create_url($file_uri)));
    '#descriptions' => array($file_description);  // ...so it can go here.
  );
}

```

As stated by Berdir, it looks that the description is stored on the file field, not on the file entity. Yes, seems to be there, somewhere in $items.

How to get it?

Many thanks.

# Answer
That's right, normally you find the values from the field in $items\[$delta\].

To make this easier for field formatters `getEntitiesToView()` puts the item in the returned array. You find the item in `_referringItem`:

```
$item = $file->_referringItem;
$description =  $item->description;

```
> 1 votes

# Answer
I had difficulties doing this too. The trick is to use `getEntitiesToView()` indeed. To get the function working, the following use statement is essential:

```
use Drupal\file\Plugin\Field\FieldFormatter\FileFormatterBase;

```

Full code for the formatter can be found here: https://stefvanlooveren.me/blog/show-file-description-custom-formatter-drupal-8
> 0 votes

---
Tags: theming, 8, entities, files
---


# Question
Title: iframe in - rewrite results - Override the output of this field with custom text
I'm trying to make a view for showing latest youtube videos in a block

I have a field called Youtube Video ID (Plain text) where I Drupal 8 stores the ID of the video...

I'm using the option of the field "Override the output of this field with custom text" in REWRITE RESULTS...

I'm doing something like this:

```
<div class='embed-container-youtube'>
<iframe src='http://www.youtube.com/embed/{{ field_id_video_de_youtube__value }}' frameborder='0' allowfullscreen></iframe>
</div>

```

Like you can see.. I'm using that mark up to show a youtube video.. taking the value of the field....

the problem is that Drupal is cleaning the iframe mark up.. I think for security...

this is how Drupal render it in the website

```
<div class="embed-container-youtube">

</div>

```

When you configure the content type you can see a note:

```
Allowed HTML tags: <a> <b> <big> <code> <del> <em> <i> <ins> <pre> <q> <small> <span> <strong> <sub> <sup> <tt> <ol> <ul> <li> <p> <br> <img>
This field supports tokens.

```

how can I add more allowed tags?

How can I allow that HTML tag for this view? ¡Thanks!

# Answer
> 1 votes
I have been wrestling with this as well but my users want to embed google docs. Same concept though.

I figured out the solution and it's not super complicated. You you just need to create a 'Field Template' in the theme.

This video covers the concept with 'Node Template' but you can easily apply it to the field template.

Drupal 8 Theming - Part 11 - Displaying Fields https://www.youtube.com/watch?v=fQ6Ypik\_jsE

# Answer
> 0 votes
I was able to get around this by including the entire iframe in the field and displaying the field as is. I avoided rewriting it anyway with views, no rewrite results or using a custom text field.

It's not ideal and means more CSS but at least the iframes are in the view.

# Answer
> -2 votes
It's been a while since this question has been asked, but in case someone searches for a solution for this problem and ends up here (like I did):

You can add the iframe-Tag to the Xss whitelist:

* Open the file core/lib/Drupal/Component/Utility/Xss.php
* Add 'iframe' to the $adminTags array

After refreshing the cache, iframe-Tags will no longer be stripped from your override text.

---
Tags: views, blocks
---


# Question
Title: just want to change checkbox value while submit
I am using drupal 7:

```
$form['title']['#tree'] = TRUE;
$form['title']['node_first'] = array(
    '#type' => 'checkboxes',
    '#options' => array(
        'value' => $value->title,
    ),
);
$form['title']['node_second'] = array(
    '#type' => 'checkboxes',
    '#options' => array(
        'value' => $value2->title,
    ),
);

```

i am getting this output after submitting (when first checkbox has been checked) :

```
    Array
(
    [title] => Array
        (
            [node_first] => Array
                (
                    [value] => value
                )

            [node_second] => Array
                (
                    [value] => 0
                )

        )
)

```

desired output:

```
Array
(
    [title] => Array
        (
            [node_first] => Array
                (
                    [value] => True
                )

            [node_second] => Array
                (
                    [value] => False
                )

        )
)

```

# Answer
> 0 votes
It should be possible to manipulate the values as desired in a custom validate function. In your form code, add something like this:

```
$form['#validate'][] = 'mymodule_custom_validate';

```

The `mymodule_custom_validate` is a function you could define as such to change the values to booleans, or anything else you need:

```
function mymodule_custom_validate(&$form, &$form_state) {
  if ($form_state['values']['title']['node_first']['value'] === 'value') {
    $form_state['values']['title']['node_first']['value'] = True;
  }
  else {
    $form_state['values']['title']['node_first']['value'] = False;
  }
  if ($form_state['values']['title']['node_second']['value'] === 'value') {
    $form_state['values']['title']['node_second']['value'] = True;
  }
  else {
    $form_state['values']['title']['node_second']['value'] = False;
  }
}

```

This is a fairly rudimentary implementation, but hopefully this will lead you in the right direction. You can see in this example how the values can be manipulated before they reach the submit handler.

# Answer
> 0 votes
Surely a single checkbox would be better?

```
$form['title']['#tree'] = TRUE;
$form['title']['node_first'] = array(
    '#type' => 'checkbox',
    '#title' => $value->title,
);
$form['title']['node_second'] = array(
    '#type' => 'checkbox',
    '#title' => $value2->title,
);

```

Form API Reference

---
Tags: 7, forms
---


title: Create views with UI Pattern Views

text:
# Question
Title: Create views with UI Pattern Views
I have views like this:

I want use module UI Pattern Views. I defined UI Pattern. File card.ui\_patterns.yml with content

```
card:
  label: Three column fluid
  description: Three column fluid
  fields:
    image:
      type: render
      label: Image
      description: Media image.
      preview:
        theme: image
        uri: http://lorempixel.com/900/500/sports/1
        width: 150
        attributes: {}
    title:
      type: link
      label: Title
      description: Media title.
      preview:
        type: processed_text
        text: <a href="#">Etiam iaculis nunc ac metus</a>
        format: basic_html

```

and file pattern-card.html.twig have content:

```
<div class="card">
    {% if image is not empty %}
        <div class="card-image">
            {{ image }}
        </div>
    {% endif %}
    <div class="card-body">
        <h4 class="card-title">{{ title }}</h4>
    </div>
</div>

```

I don't know how can use multil image style for this case. Any suggetion?

# Answer
Here's a step-by-step:

* Install the UI Patterns Views module
* Insert the fields and map them to the UI Pattern fields
    + **Note:** You are mapping fields for the rows.

At this point, each piece of content should be rendered as a UI Pattern

Now, if you want to arrange the cards in a specific way (say, using Masonry), then you can do it in one of the following ways:

* Add a class to the entire view, say, `js-view-masonry` – you can then use this class in JavaScript to detect this view and apply the JS plugin that organizes the cards like you want.
* The other way will be to create a superpattern of the `card` pattern. Say, a `card_collection` pattern, with a field named `items`. Next, override the view's template, especially the part where the rows are rendered. Here, instead of displaying the rows, into the "card\_collection" pattern.

Here's a working example of the second method using "card\_collection". The blog list consists of 2 patterns. The "card" pattern and a pattern called "card collection" which wraps the cards.
> 0 votes

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


# Question
Title: How do you get Product Variation Type fields and display modes to show up when displaying Products in a View?
I've created a Product Variation Type for all my products, all of which have the following custom fields: *Display Title*, *Subtitle*, and *Top Rated Product?* (boolean checkbox):

When setting up a View to display my Products, I am unable to access any of these fields, regardless of whether I choose "Fields" or "Content" under "Format \> Show:". Nothing shows up:

I also can't access any of the display modes I created for Products — not even the default "Cart" display mode shows up here:

Am I missing something that's required to get this working properly? I can only choose "Fields", "Product", or "Search Results", and like I said, even when I choose "Fields", I can't find any of the custom fields for my Products.

# Answer
It turns out that I had to add a relationship to *Product Variation Type* in order for those fields to show up. Hope this helps others!
> 0 votes

---
Tags: views, 8, commerce
---


title: How to make Title Filed Required

text:
# Question
Title: How to make Title Filed Required
I have migrated my Drupal 7 website to Drupal 8. The content types are showing title as optional and when we save a node without adding the title it's giving the fatal error.

How can we make the title field compulsory?

**Note**: I know title field is required by default, and it is required by default in my Drupal 7 site. But after migrating the site to Drupal 8 it's not showing required. Is it possible if export content types configuration from my new site and edit the configuration and import them again to fix this issue?

# Answer
> 1 votes
You can indeed edit the exported config and then re-import it to make the title field mandatory.

**Always be careful when editing config directly.**

The config files generally follow the naming convention `core.base_field_override.<entity_type>.<bundle>.title.yml`.

There should be a `required` key which is set to `false`. Simply change `false` to `true`, save and then re-import your config.

---
Tags: 8, migrations
---


# Question
Title: How to get the enabled manage displays per node type?
I have an admin form and need to check if a node, e.g. article has a specific manage display enabled. How do I get the data?

Found out to get an array of all available displays in general and there is a difference between display views and view modes. May I am just searching with the wrong terms.

# Answer
You can use this service:

**EntityDisplayRepository**

> Provides a repository for entity display objects (view modes and form modes).

Example:

```
$view_modes = \Drupal::service('entity_display.repository')
  ->getViewModeOptionsByBundle('node', 'article');

```

More info: https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Entity%21EntityDisplayRepository.php/class/EntityDisplayRepository/8.2.x
> 1 votes

---
Tags: 8
---


# Question
Title: How to create a list of users who did not submit some webform?
I have a webform expecting all users to record their data online.

I would like to list all users who did not submit the webform yet. I have been trying to use Views, but I cannot find a way to do that.

To list users who have submitted is not a problem, just display the users submitting in Views table.

How can I list all users who did not submit the webform?

# Answer
# Step 1 - Introduce a webform submission flag

Install/enable the Flag module. Navigate to `/admin/structure/flags/add/node` and create a flag (do not check the "global" checkbox). Let's assume you label it something like "*Webform submission*". For "Bundles" (on the same form), check "Webform".

Here is such Flag definition (in export format) you could use for it (just import it in your own site):

```
$flags = array();
// Exported flag: "Webform submission".
$flags['webform_submission'] = array (
  'entity_type' => 'node',
  'title' => 'Webform submission',
  'global' => '0',
  'types' =>
  array (
    0 => 'webform',
  ),
  'flag_short' => 'Webform submitted',
  'flag_long' => 'Indication that the Webform was submitted already',
  'flag_message' => 'Webform submission recorded',
  'unflag_short' => 'Webform NOT submitted',
  'unflag_long' => 'Indication that the Webform is not yet submitted',
  'unflag_message' => 'Webform submission recording removed',
  'unflag_denied_text' => '',
  'link_type' => 'toggle',
  'weight' => 0,
  'show_in_links' =>
  array (
    'full' => 0,
    'teaser' => 0,
    'rss' => 0,
    'search_index' => 0,
    'search_result' => 0,
    'answers_full_node' => 0,
    'print' => 0,
  ),
  'show_as_field' => 0,
  'show_on_form' => 0,
  'access_author' => '',
  'show_contextual_link' => 0,
  'i18n' => 0,
  'api_version' => 3,
);
return $flags;

```

# Step 2 - Register webform submissions

Install/enable the Rules module and create a Rule to flag the webform when it is submitted (by the user who submitted the webform and using the flag "Webform submission" (from Step 1).

Here is such Rule definition (in export format) you could use for it (just import it in your own site, which you can do if you have the 'Rules UI' enabled):

```
{ "rules_flag_a_submitted_webform" : {
    "LABEL" : "Flag a submitted webform",
    "PLUGIN" : "reaction rule",
    "OWNER" : "rules",
    "REQUIRES" : [ "rules", "flag", "webform_rules" ],
    "ON" : { "webform_rules_submit" : [] },
    "IF" : [
      { "data_is" : { "data" : [ "node:nid" ], "value" : "5" } },
      { "user_has_role" : { "account" : [ "user" ], "roles" : { "value" : { "2" : "2" } } } }
    ],
    "DO" : [
      { "flag_flagnode" : {
          "flag" : "webform_submission",
          "node" : [ "node" ],
          "flagging_user" : [ "user" ],
          "permission_check" : "1"
        }
      }
    ]
  }
}

```

# Step 3 - List the webform submissions

Create a view (using the Views module), to list the user who have yes or no flagged the webform with the "Webform submission"-flag from Step 1).

Here is such Views definition (in export format) you could use for it (just import it in your own site, which you can do if you have the 'Views UI' enabled):

```
$view = new view();
$view->name = 'webform_submissions_by_users';
$view->description = '';
$view->tag = 'default';
$view->base_table = 'users';
$view->human_name = 'Webform submissions by users';
$view->core = 7;
$view->api_version = '3.0';
$view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */

/* Display: Master */
$handler = $view->new_display('default', 'Master', 'default');
$handler->display->display_options['title'] = 'Webform submissions by users';
$handler->display->display_options['use_more_always'] = FALSE;
$handler->display->display_options['access']['type'] = 'perm';
$handler->display->display_options['access']['perm'] = 'access user profiles';
$handler->display->display_options['cache']['type'] = 'none';
$handler->display->display_options['query']['type'] = 'views_query';
$handler->display->display_options['exposed_form']['type'] = 'basic';
$handler->display->display_options['pager']['type'] = 'full';
$handler->display->display_options['pager']['options']['items_per_page'] = '10';
$handler->display->display_options['style_plugin'] = 'table';
/* Relationship: Flags: User's flaggings */
$handler->display->display_options['relationships']['flag_user_content_rel']['id'] = 'flag_user_content_rel';
$handler->display->display_options['relationships']['flag_user_content_rel']['table'] = 'users';
$handler->display->display_options['relationships']['flag_user_content_rel']['field'] = 'flag_user_content_rel';
$handler->display->display_options['relationships']['flag_user_content_rel']['required'] = 0;
$handler->display->display_options['relationships']['flag_user_content_rel']['flag'] = 'webform_submission';
/* Field: User: Name */
$handler->display->display_options['fields']['name']['id'] = 'name';
$handler->display->display_options['fields']['name']['table'] = 'users';
$handler->display->display_options['fields']['name']['field'] = 'name';
$handler->display->display_options['fields']['name']['alter']['word_boundary'] = FALSE;
$handler->display->display_options['fields']['name']['alter']['ellipsis'] = FALSE;
/* Field: Flags: User uid */
$handler->display->display_options['fields']['uid']['id'] = 'uid';
$handler->display->display_options['fields']['uid']['table'] = 'flagging';
$handler->display->display_options['fields']['uid']['field'] = 'uid';
$handler->display->display_options['fields']['uid']['relationship'] = 'flag_user_content_rel';
/* Field: Flags: Flagged time */
$handler->display->display_options['fields']['timestamp']['id'] = 'timestamp';
$handler->display->display_options['fields']['timestamp']['table'] = 'flagging';
$handler->display->display_options['fields']['timestamp']['field'] = 'timestamp';
$handler->display->display_options['fields']['timestamp']['relationship'] = 'flag_user_content_rel';
$handler->display->display_options['fields']['timestamp']['date_format'] = 'long';
$handler->display->display_options['fields']['timestamp']['second_date_format'] = 'long';
/* Sort criterion: User: Uid */
$handler->display->display_options['sorts']['uid']['id'] = 'uid';
$handler->display->display_options['sorts']['uid']['table'] = 'users';
$handler->display->display_options['sorts']['uid']['field'] = 'uid';
/* Filter criterion: Flags: User uid */
$handler->display->display_options['filters']['uid']['id'] = 'uid';
$handler->display->display_options['filters']['uid']['table'] = 'flagging';
$handler->display->display_options['filters']['uid']['field'] = 'uid';
$handler->display->display_options['filters']['uid']['relationship'] = 'flag_user_content_rel';
$handler->display->display_options['filters']['uid']['value'] = '';
$handler->display->display_options['filters']['uid']['exposed'] = TRUE;
$handler->display->display_options['filters']['uid']['expose']['operator_id'] = 'uid_op';
$handler->display->display_options['filters']['uid']['expose']['label'] = 'User uid';
$handler->display->display_options['filters']['uid']['expose']['use_operator'] = TRUE;
$handler->display->display_options['filters']['uid']['expose']['operator'] = 'uid_op';
$handler->display->display_options['filters']['uid']['expose']['identifier'] = 'uid';
$handler->display->display_options['filters']['uid']['expose']['remember_roles'] = array(
  2 => '2',
  1 => 0,
  3 => 0,
  4 => 0,
  5 => 0,
  6 => 0,
);
/* Filter criterion: User: Active */
$handler->display->display_options['filters']['status']['id'] = 'status';
$handler->display->display_options['filters']['status']['table'] = 'users';
$handler->display->display_options['filters']['status']['field'] = 'status';
$handler->display->display_options['filters']['status']['value'] = '1';

/* Display: Page */
$handler = $view->new_display('page', 'Page', 'page');
$handler->display->display_options['path'] = 'webform-submissions-by-users';

```

# Fruit of your labor

If you import the above definitions of the flag, the rule and the view, and you have a few users submit the webform (= record their data), you can visit the relative path in your own site, which should then display a table that looks similar to this example:

```
Name            User uid   Flagged time
--------------+----------+--------------------------------
Demo.User     !          !
Famous.Dries  ! 8        ! Wednesday, May 11, 2016 - 19:13
Pierre.Vriens ! 19       ! Wednesday, May 11, 2016 - 18:07

```

For the above example, user "Demo.User" had not yet submitted the webform. The view contains an exposed filter so that you can limit the display to only those who submitted the form, or those who did not yet submit the form.

# Start nagging users

If you would enhance your view from Step 3 with the Views Bulk Operations module, and you'd create a Rules Component (using the Rules module) to send an eMail, you could use it to eMail all those users in that view with some type of nagging eMail like "*Please record your data...*".

# What's next?

The above doesn't take into account any webform submissions from before the above logic is implement. However it should be pretty forward to use a mixture of the above (4) modules, including VBO, to perform such one time only update (to also flag the users who already submitted the webform in the past). Anybody interested in knowing about that: Ask (a followup) Question ...
> 2 votes

# Answer
Well above solution may work but it looks far too complex to my eyes. ;)

I have achieved this on Drupal 8 by following below steps,

1. Create a user view
2. Load user data into fields
3. Add relationship to "webform submissions" (Do not enable "Require this relationship")
4. Add filter "Webform submission: Submitted by"
5. Set that filter to "Is Empty (NULL)"

This will show all users who have not submitted any webform.

to target a specific webform, create a user role and give access to only that role for that specific webform.

Or there is another filter, where you can select specific webform but somehow it does not work on my drupal site. You can give it a try, it may work on your drupal site.

This should also work for Drupal 7, I haven't tried it.

Enjoy :)
> 2 votes

---
Tags: views, webforms
---


# Question
Title: How do I get the form submitted data in a custom module?
I have create a webform in Drupal 7. I want to access the submitted data in a custom module.

I used `my_module_form_submit($form, &$form_state)` but no data has been found.
Please Help.

# Answer
> 1 votes
You have to get submitted data based on sid, I think below code will be helpful for you

```
 function MYMODULE_form_alter(&$form, &$form_state, $form_id){
  if ($form_id == 'WEBFORM_'){
module_load_include('inc','webform','includes/webform.submissions');
$sid = 10;
$submission = webform_get_submissions(array('sid' => $sid));
$nid = $submission[$sid]->nid;

$web_submission = webform_get_submission($nid, $sid);
$node = node_load($nid);
$output = webform_submission_render($node, $web_submission, NULL, 'html');

print $output;
}

```

# Answer
> 0 votes
You have to do hook\_form\_alter() and change the submit function. Below is the code"

```
function MYMODULE_form_alter(&$form, &$form_state, $form_id){
  if ($form_id == 'WEBFORM_'){ // give your webform id here.
    if (isset($form['actions']['submit'])) {
     $form['actions']['submit']['#submit'][] ='webform_custom_submit';
    }
  }
}

function webform_custom_submit(&$form, &$form_state){
  $values = $form_state['values']; // Here you can get all $form_state values
}

```

---
Tags: 7, forms
---


# Question
Title: How to redirect to another page using the url alias?
Here is my code where I am trying to redirect to a page using its url alias:

```
    $url= Url::fromUserInput('/thank_you_for_your_message')->toString();
    $form_state->setRedirect($url);
    return;

```

and I get this error : `Symfony\Component\Routing\Exception\RouteNotFoundException: Route "/thank_you_for_your_message" does not exist. in Drupal\Core\Routing\RouteProvider->getRouteByName()`

Is the fromUserInput the correct way to redirect to an internal url alias?

# Answer
Here you can see an example that works for me:

I use `'internal:url-alias'`

```
use \Drupal\Core\Url;
...

$search_page = '/en/faith-community/find-a-parish';
$form_state->setRedirectUrl(Url::fromUri('internal:' . $search_page));

```
> 6 votes

# Answer
to ensure that the internal alias exists, check for the route before trying to redirect

```
$search_page = Url::fromUri ('internal:/en/faith-community/find-a-parish');

if ($search_page->isRouted()) {
  $form_state->setRedirectUrl($search_page);
}

```
> 1 votes

---
Tags: 8, forms, redirection
---


# Question
Title: "Edit layout" form missing revision log message field
When I edit the layout for a given node it is missing a log message field in the revision area. Is anybody else seeing this or am I alone? In trying to diagnose:

* Where that particular revision log field would be defined to check if it's defined at all. If it's not then this is probably a core bug that should be addressed.
* If it does exist, where this particular form is defined to make sure that the revision log field is actually being included in the form definition.

Any insights on the above? I'm using the lightning distribution, so it's possible that there's some sort of override going on there, but I figured I should be checking in core first just in case.

The overall goal here for bounty award is to have a functional revision log message field on the form.

# Answer
> 3 votes
I've added my initial patch to the issue - https://www.drupal.org/project/drupal/issues/3033516#comment-13136184

Adding this chunk to the `init` method of the `OverridesEntityForm` seems to do the trick, at least for nodes. We'll see what core maintainers come back with, but hopefully this can help you in the meantime.

```
  /**
   * {@inheritdoc}
   */
  protected function init(FormStateInterface $form_state) {
    parent::init($form_state);

    $form_display = EntityFormDisplay::collectRenderDisplay($this->entity, $this->getOperation(), FALSE);
    $form_display->setComponent(OverridesSectionStorage::FIELD_NAME, [
      'type' => 'layout_builder_widget',
      'weight' => -10,
      'settings' => [],
    ]);

    $section_storage = $this->getSectionStorage();
    $entity = $section_storage->getContextValue('entity');
    $entity_type = $entity->getEntityType();
    if ($entity_type->isRevisionable()) {
      $revision_log_message_form_item = $entity_type->getRevisionMetadataKey('revision_log_message');
      $log_field_definition = $entity->getFieldDefinition($revision_log_message_form_item);
      $log_field_revision_message_form_data = $log_field_definition->getDisplayOptions('form');
      $form_display->setComponent($revision_log_message_form_item, $log_field_revision_message_form_data);
    }

    $this->setFormDisplay($form_display, $form_state);
  }

```

# Answer
> 0 votes
It seems a bug in the Layout Builder Module.
I found an issue on the Drupal Core issue queue with the same exact behaviour. Strangely, it is marked as "Closed (cannot reproduce)"
I did create a clean Drupal 8 instance, enabled Layout Builder for the basic page content type with enabled revisions.
I saw the same exact behaviour. Additionally, log messages were only saved with "edit" form and not with the "layout" form. So, it is definitely a core layout builder module bug and not related to the distribution you're using.

---

**Suggestion**: Open a new ticket on the Drupal Core issue tracker

---
Tags: 8
---


# Question
Title: How owerride entity node delete core function
I'm doing a headless drupal cms.

I need to check the entities before they are deleted. I need to do it globally as the deletion of entities can take place via api (already written) or by using the cms as an administrator.

How can I overwrite the "delete" core operation? I've tried using hooks (hook\_entity\_predelete / hook\_entity\_delete) but they don't block delete operation. I need something like this:

```
if ($condition == true)
  core_delete()
else
  disable_core_delete()

```

Thank you

# Answer
> 1 votes
The only way I can think to do this is to override the entity's storage handler in hook\_entity\_type\_alter() with a storage handler that provides the delete functionality you want.

Something like

```
// You're going to want to be sure you're extending the entity's original
// storage handler.
class CustomStorageHandler extends EntityStorageBase {

  /*
   * {@inheritdoc}
   */
  public function delete(array $entities) {
    array_filter($entities, function ($entity) {
      // Do your logic to determine if the entity should be deleted here.
      // This example only allows entities with odd ids to be deleted.
      return (bool) $entity_id % 2;
    }
    parent::delete($entities)
  }
}

```

It is probably a better idea, however, to use the entity's access system to prevent users from deleting entities as it will be confusing to try to delete an entity, then for that to not happen.

---
Tags: database, hooks
---


# Question
Title: How to remove arrows from views Select list field
I have a content type which has a select list field.

I created a view where select list field was added under "filter criteria".

How can I remove the arrows and slider?

# Answer
The appearance of the Select widget on a Content type can be changed on the `Manage form display` page for that Content type (for example for Article CT it's under `Structure > Content types > Article > Manage form display` (`/admin/structure/types/manage/article/form-display`)).

For a List field you can change it from the `Select list` to `Check boxes/radio buttons`.

There are also modules that provide different widgets for these types of fields, for example Select 2.

---

In Views you can change how each of the Exposed form elements is rendered under Advanced (third column area) \> `Exposed form style` settings.

The module Better Exposed Filters is commonly used to adjust the Views Exposed forms.
> 1 votes

---
Tags: views
---


# Question
Title: Creating 'index' content views for L1-LX within a taxonomy
Note: This is a follow-on question from Creating a displayable 'index' of content nodes within a path

Ok, starting to find my feet again within Drupal, and still getting up to speed with views.

**What I'm needing help with**

1. How do I update my view for /documentation, to display the results in a proper HTML ordered and numbered list that follows the taxonomy structure? (i.e. 1. SOP, 1.1 HR and People, 1.2 HACCP, and so on)
2. How do I then easily duplicate the view's functionality to the L2, L3 and beyond, so this kind of display runs at every level of the taxonomy when it is accessed - i.e. /documentation/hr-people, /administration/fleet/maintenance etc. Does doing this require a content view to be created for every single level/tree in my Content zone taxonomy (which I would think is cumbersome and laborious), OR is there a way to have only a single view with the intelligence to know what page it's being run on within the taxonomy and only display the relevant results at that level?

(I hope the way I've framed this question and the supporting materials below make perfect sense)

**Explanation**

Following on from the assistance of Hodba Khalaf, I've been able to create my documentation taxonomy (called content zone) for my site, which looks a little something like this:

I've also been able to create a View (called Content zone), targeting the Content zone taxonomy:

This works fine at L1 (/documentation) - with the exception that I'm not entirely sure how to make display the resulting information in an ordered and numbered list relevant to how the taxonomy is laid out, rather than the alphabetical order in which it is displayed.

And from there, clicking on one of the links for a L2 within my taxonomy (say /documentation/marketing) will show all the content assigned to that L2 within the taxonomy; but won't show the L3 headers and links (i.e. /documentation/marketing/advertising, /documentation/marketing/email-waf) of the taxonomy associated with the L2 of Marketing

I hope what i'm trying to achieve has made sense, and appreciate all and any help to point me in the right direction for achieving this.

# Answer
> 0 votes
1. There are features in Views concerning taxonomy hierarchy, displaying terms with depth, you should look into it. There is also Group by field option under Format in Views where you can, for example, group by Parent field (Parent of the Taxonomy term). You may need to add a Relationship for the Taxonomy field first before you can see those extra Fields/Filters. Contextual filter with depth might also be useful.
2. You should look into displaying Menus with depth, since each Taxonomy Vocabulary already has a Menu block. You can learn more about it here: Primary and Secondary Navigation in Drupal 8

Generally speaking, you want to get to a point where you have correctly nested HTML list items. Then you can use CSS to adjust the numbering to go into levels 1.1, 1.2 etc.

Or if that numbering is so important you could add a field for it on your Vocabulary, so each item has that textual bit of data associated with it (not numbers because the sorting won't be correct, you want 1.10 \> 1.1). Sorting in Views can still be done with the term weight (the sorting you saved in Taxonomy).

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


# Question
Title: How to use CiviCRM contact data latitude and longitude in drupal gmap formatted view
**Environment** Drupal 7.67 civicrm 7.x-5.13.4 GMap Module 7.x-2.11 Location 7.x-3.7 Views 7.x-3.23

**What is working** I have CiviCRM contact data for organisations which has been successfully geocoded using google I have view in Drupal that can access and display this contact data in a table including company names and latitude and longitude I can display a google map in the contact record in CiviCRM, so I know the Lat & Long is correct

**Problem** When I change from a table to a gmap format in the view no map is displayed,

View setup

> Format Format:GMap | Settings Show:Fields | Settings open Add Fields CiviCRM Website: Website URL (Website) CiviCRM Contacts: Contact ID CiviCRM Contacts: Organization Name (Retailer) CiviCRM Address: Full Street Address (Address) CiviCRM Address: Postal Code (Postcode) CiviCRM Phone Details: Phone (Phone) CiviCRM Tags: Name (Name) CiviCRM Custom: Organisation Fields: LALG Member Benefits (LALG Member Benefits) CiviCRM Address: Latitude (Latitude) CiviCRM Address: Longitude (Longitude)

GMap format settings

> Grouping field Nr.1
>
> You may optionally specify a field by which to group the records. Leave blank to not group. Macro \[gmap \] Enter a macro. If left unchanged, it takes the default settings from /admin/config/services/gmap. See the documentation on GMap macros. Data Source
>
> Latitude field -\> Latitude
>
> Format must be degrees decimal. Longitude field -\> Longitude
>
> Format must be degrees decimal. Marker handling

I am also log messages when executing the view:

> php Fri 7 Jun - 10:43am Notice: Array to string conversion in strtr() (line... gjw
> php Fri 7 Jun - 10:43am Notice: Array to string conversion in strtr() (line... gjw php Fri 7 Jun - 10:43am Notice: Array to string conversion in strtr() line... gjw php Fri 7 Jun -\> 10:43am Notice: Array to string conversion in strtr() (line... gjw

Details

> Type php Date Friday, 7 June 2019 - 10:43am User gjw Location https://ref.lalg.org.uk/admin/structure/views/view/retailers/edit/retailers?destination=retailers Referrer https://ref.lalg.org.uk/retailers Message Notice: Array to string conversion in strtr() (line 1835 of /var/sites/r/ref.lalg.org.uk/public\_html/includes/bootstrap.inc). Severity notice

# Answer
There is a good recipe for using leafhttps://civicrm.stackexchange.com/questions/12862/how-to-put-your-civicrm-contacts-on-a-leafleft-map-in-5min if you are happy to slightly switch track. For D7

Also you will get more Civi eyeballs if you post on that channel, and while I appreciate this is a 'drupal' question, more civi folk use drupal than drupal folk use civi ;-). Good luck
> 0 votes

---
Tags: views, google-maps, civicrm
---


# Question
Title: Site migrated to the new server with PHP 7.2 and I can't log in
We're preparing to get our Drupal infrastructure moved from PHP 5.6 to PHP 7.2. In order to start testing, I migrated a Drupal 7.67 multi-site from our current production server to a test server running PHP 7.2 and got one of the sites configured. So far, everything about the web site appears to work fine (visual, navigation, etc). Except that I can't log in!

When I navigate to /user/login, type my username and password, and click submit, there's evidence in the database that the login appears successful (users.login timestamp updates), and I'm redirected to /users/myusername, but it says "Access Denied" and doesn't show the top bar to change config, content, etc.

Drush appears to work fine for changing my password (upwd), creating one-time login links (uli), etc, but the login link doesn't work, instead showing "Access Denied" again.

I've checked just about everything you're supposed to check when issues like this come up:

* Verified mod\_rewrite is enabled
* Tried with and without Base URL setting enabled in settings.php
* Tried with and without RewriteBase setting in .htaccess
* Tried with and without cookie\_domain setting in settings.php
* Cleared caches and truncated tables like cache\*, flood, semaphore, sessions, watchdog
* Made sure no database updates are pending
* Restarted Apache periodically
* Checked Apache error logs, nothing of note there
* Tried multiple browsers from multiple computers, with and without Incognito modes

I have no idea what else to try, and sadly I'm not even sure if this is simply related to migrating the site from one server to another or whether it's because we moved from PHP 5.6 to PHP 7.2. Where do I begin troubleshooting this? Thank you in advance for your help!

# Answer
We found the problem. The site was using HTTPS on the production server and HTTP on the test server, and we had set `php_flag session.cookie_secure On` in our Apache config. HTTPS wasn't in use, so no cookies were sent, so no logins would work properly. Setting this to `Off` worked wonders. Thanks for pointing me in the right direction, folks!
> 0 votes

---
Tags: 7, migrations
---


title: Migration via phpmyadmin

text:
# Question
Title: Migration via phpmyadmin
We are moving to a Drupal distribution. From all the research we have done, there is no easy path to do Drupal 8 to Drupal 8 migration.

We are looking to copy some content via phpmyadmin.

Data we need to move are:

* Taxonomy
* Nodes
* Comments

Which tables do we need to copy from one database to the new?

We did copy the users successfully.

Now wondering if we can do the content as well.

# Answer
if migration sounds too hard ...

install and config https://www.drupal.org/project/default\_content\_deploy

then

```
"drush default-content-deploy:entity-list"

```

to see a list then:

```
"drush default-content-deploy:export taxonomy_term"
"drush default-content-deploy:export node"
"drush default-content-deploy:exportcomment"

```

copy the exported files to your next site, make sure the nodes taxonomy\_terms and comments have same field structure (can do this by exporting / importing config or look at features module)

after that import your content.

```
   "default-content-deploy:import"

```

again make backups of your "new" database before this though !

extra bonus use version control on the exported content .. that way developers / live sites can share the content easily.
> 0 votes

---
Tags: 8, migrations
---


# Question
Title: Close webform modal and redirect to entity
I have a webform that opens inside a modal. Everything works fine. Then I had the problem of closing the modal after the form was submitted. I fixed that to with the help of the following link: https://www.drupal.org/project/webform/issues/3002966#comment-12794056

I have a webform handler that creates a new entity in the `postSave()` method. After this entity is created, I want to close the modal and redirect to the entity detail page. What is the best/correct way to do this. I could use a `RedirectCommand` instead of the `CloseDialogCommand` but how do I get the entity id in the `_CUSTOM_MODULE_webform_submission_form_submit_ajax()` method. Using the AjaxResponse with a `RedirectCommand` in the `postSave()` method didn't work.

Any Suggestions would be great ;-)

# Answer
Yes you are so close! just move the creation of the new entity from your postSave() to right in the ajax call back

```
example:

_CUSTOM_MODULE_webform_submission_form_submit_ajax(array &$form, FormStateInterface $form_state) {
 // At this point we have all access to $form_state->getValues();
 // the webform submission is all ready saved so we can use the values here.

 // Get the entity storage.
 $entity_storage = \Drupal::entityTypeManager()->getStoage('ENITYNAME');

  // Create New entity.
  $new_entity = $entity_storage->create([
   'field_whatever' => $form_state->getValue('some_field');
  ]);
  // Save entity
  $new_entity->save();
  $new_entity_id = $new_entity->id();
  // set the url.
  $url = "/where-ever/" . $new_entity_id;

  $response = new AjaxResponse();
  $response->addCommand(new CloseModalDialogCommand());
  $response->addCommand(new RedirectCommand($url);
  // Party.
 return $response;
}

```
> 1 votes

---
Tags: 8, webforms
---


# Question
Title: Adding local task tabs to node display for specific content type
I'm creating a custom module (it's called cil\_meet) which adds two content types (organisation and room). On an organisation node I want a local task tab (next to 'view' and 'edit') of 'add room', for administrators. On a room node I want two tabs 'publish' and 'info'.

After some research, I've figured out a way to achieve this, but I want to know if there is a better way of doing this?

**cil\_meet.routing.yml:**

```
cil_meet.addroom:
  requirements:
    _role: 'administrator'
cil_meet.roompublish:
#  path: '/meet/{organisation}/{room}/publish'
  requirements:
    _role: 'authenticated'
cil_meet.roominfo:
#  path: '/meet/{organisation}/{room}/info'
  requirements:
    _role: 'authenticated'

```

I've commented out the path for publish & info for now - I'll set up controllers, etc later.

**cil\_meet.links.task.yml:**

```
cil_meet.addroom:
  route_name: 'node.add'
  title: 'Add Room'
  weight: 100
  route_parameters:
    node_type: 'room'
  base_route: entity.node.canonical
cil_meet.roompublish:
  route_name: 'cil_meet.roompublish'
  title: 'Publish'
  weight: 100
  base_route: entity.node.canonical
cil_meet.roominfo:
  route_name: 'cil_meet.roominfo'
  title: 'Info'
  weight: 101
  base_route: entity.node.canonical

```

This adds the tabs to all nodes. So to remove the tabs from anything other than organisation or room nodes, I've got to add some code to the module.

**cil\_meet.module:**

```
<?php
/**
 * Implements hook_local_tasks_alter().
 */
function cil_meet_menu_local_tasks_alter(&$local_tasks, $route_name) {
    $route_match = \Drupal::routeMatch();

    if ($route_match->getRouteName() == 'entity.node.canonical') {
        $node = $route_match->getParameter('node');
        if($node->bundle()!='organisation') {
            unset($local_tasks['tabs'][0]['cil_meet.addroom']);
        }

        if($node->bundle()!='room') {
            unset($local_tasks['tabs'][0]['cil_meet.roompublish']);
            unset($local_tasks['tabs'][0]['cil_meet.roominfo']);
        }
    }
}

```

All works as expected, the above may help others needing a similar solution. Is there a better way of doing this?

# Answer
Solution from Matt B only hides the tab on the node view page, but not on the node edit etc. The direct url will also be accessible in that case.

A better solution is to write a custom access handler

See Custom validation of route parameters
> 3 votes

---
Tags: 8
---


# Question
Title: How to get and display menu items except the parent item?
Let's say my menu tree is like below:

* Parent
    + Sub-Parent
        - Child

I want to get the Sub-Parent title and all child's title and url.

How can I do it in Drupal 8?

I have looked at this answer but it just for getting the parent, it is not the one I'm looking for.

# Answer
> 0 votes
Given the answer you mentioned, I assume that you would like to retrieve your items data programmatically.

What you are missing is the `setRoot()` method from `MenuTreeParameters` (here). Here is how you could start with:

```
    $menuTree = \Drupal::menuTree();

    $menuTreeParameters = new MenuTreeParameters();
    // This will fetch the tree starting from your Sub-Parent
    $menuTreeParameters->setRoot('sub_parent_link_plugin_ID');
    // Set the nb of levels, starting from root you defined, that you want to fetch (0 = all)
    $menuTreeParameters->setMaxdepth(1);

    // Load tree based on your parameters
    $myMenuTree = $menuTree->load('name_of_your_menu', $menuTreeParameters);
    // List of Sub-parent children items
    $subtree = $myMenuTree['sub_parent_link_plugin_ID']->subtree;

```

`$myMenuTree` will give you data about Sub-Parent as a MenuLinkTreeElement. `$subtree` will correspond to its children, each as a MenuLinkTreeElement as well.

In each of these two variables, you will find for each MenuLinkTreeElement a `link` entry of type `MenuLinkContent` containing all the data about your menu link item. Starting from `link`, you would be able to use the `MenuLinkContent` methods to retrieve the title and url of each of your items.

Hope this helps.

# Answer
> 0 votes
You can do this by configuring the `Menu levels` on your Menu Block and placing that Block in a region of your theme. Additionally configure the Visibility of the block so it only appears on pages where you want it.

You can learn more about the Menu levels configuration here: Drupal 8 Navigation Menu Blocks configuration.

In your case you want the **Initial visibility level** and **Number of levels to display** to be either:

`1` and `3`

OR

`2` and `3`

AND

you'll want the **Expand all menu items** to be checked, unless you have all the items Expanded under Menu settins.

---
Tags: blocks, navigation
---


# Question
Title: Accessing the uri within the template_preprocess_image_formatter
I am using template\_preprocess\_image\_formatter and I am trying to access the uri protected property inside the URL array (see screenshot)

does anybody know how to access it?

# Answer
i've sorted it

you can do it like this

```
$variables['url']->getUri()

```
> 0 votes

---
Tags: 8, hooks
---


# Question
Title: How to handle exceptions in a batch process
I have some special configured content entities in my system which are protected in a pre-delete hook against entity deletion. There is also a batch process (VBO - entity delete) where they can be selected before hand.

I want to handle gracefully the exception in a batch process which wasn't written by me (and cannot be touched). I tried to subscribe to the exception event and look for xmlHttpRequest which was all fine, but then I dunno what response to set back to stop the process, or log the exception within the batch process with the proper message. What I always get back is this, where the error message is what I put into the AjaxResponse body:

Any help appreciated find a more sophisticated solution to redirect from the batch processing in case of an exception.

# Answer
So in the end I took and overrode the plugin provided by the VBO. This will put the exception message into the summary displayed with a `drupal_set_message` at the end of the batch process (VBO 3.0.0-alpha2).

```
namespace Drupal\my_module\Plugin\Action;

use Drupal\views_bulk_operations\Plugin\Action\EntityDeleteAction;

/**
 * Delete entity action with default confirmation form.
 *
 * @Action(
 *   id = "my_module_delete_entity",
 *   label = @Translation("MyModule Delete selected entities"),
 *   type = "",
 *   confirm = TRUE,
 * )
 */
class MyModuleEntityDeleteAction extends EntityDeleteAction {

  public function execute($entity = NULL) {
    try {
      $entity->delete();
      return $this->t('Delete entities');
    }
    catch (\Exception $e) {
      return $e->getMessage();
    }
  }

}

```
> 3 votes

---
Tags: 8, batch-operations
---


# Question
Title: Drupal::request()->request->all() returns an empty array
I have a custom controller that expects POST data. I had it working fine in 8.1.0 retrieving the data using `\Drupal::request()->request->all()` and `\Drupal::request()->request->get($myvar)`.

Now, without any changes in my custom module, `\Drupal::request()->request->all()` is returning an empty array, and `\Drupal::request()->request->get($myvar)` is returning `NULL`.

Between the time it was working and when the issue arose, my hosting service Pantheon updated their Drupal 8 version from 8.1.0 to 8.1.1 and then 8.1.2. I suspect something may have changed then that affected this.

How can I fix this?

**EDIT**: Thanks for the comments, still not quite working...

Route YAML:

```
mymodule.foobar:
  path: '/foobar'
  options:
    _auth: [ 'basic_auth' ]
  defaults:
    _controller: '\Drupal\mymodule\Controller\FooBarController::foobar'
    _title: 'foobar'
  requirements:
    _user_is_logged_in: 'TRUE'
    _permission: 'administer site configuration'

```

Controller:

```
<?php
namespace Drupal\mymodule\Controller;
use Drupal\Core\Controller\ControllerBase;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
/**
 * Class FooBarController.
 *
 * @package Drupal\mymodule\Controller
 */
class FooBarController extends ControllerBase {
  /**
   * Provides content for the /mymodule/foobar path.
   *
   * @param \Symfony\Component\HttpFoundation\Request $request
   *   The current request
   */
  public function foobar(Request $request) {
    $content = $request->getContent();
    $data = array();
    $data['a'] = $request->get('foo');
    $data['b'] = $request->request->get('foo');
    $data['c'] = \Drupal::requestStack()->getCurrentRequest()->request->get('foo');
    $data['e'] = $request->request->all();
    $data['f'] = $content;

    $request = \Drupal::requestStack()->getCurrentRequest();
    $content = $request->getContent();
    $data['g'] = $request->get('foo');
    $data['h'] = $request->request->get('foo');
    $data['j'] = $request->request->all();
    $data['k'] = $content;

    return new JsonResponse((object) $data);
  }
}

```

Postman Request:

Note: This was working before with this exact code, correctly using basic HTTP authentication. There have been no changes other than these variations to my controller, and core updates.

Any more ideas?

# Answer
> 0 votes
I had the same issue and the request parameters were always empty. I think it could be due to using it in a controller rather than a REST endpoint but I'm not sure.

The following line of code worked for me:

```
$request->getContent();

```

# Answer
> -1 votes
Try this:

```
$request = \Drupal::requestStack()->getCurrentRequest()->query->all();

```

**Sidenote:** Using a Controller you shouldn't use "\Drupal::..." static request call. Instead, you always have in your controller's enter point function a "Request $request" object as a last argument.

---
Tags: 8
---


# Question
Title: Rules to clear commerce cart on adding new item of a different product type
I've several product type with corresponding product displays. The scenario is a case where there is only a product type per time on the cart. That is, you cannot have multiple product types at the same on the cart. Hence, each time a new item is to be added, check if it is of the same type as the existing items in the cart. If it is add, if not clear cart before adding the new item.

What rule setting can help me in achieving this. Thank you.

# Answer
> 1 votes
Found answer to my own question. I discovered the conditional rules module and came up with this rule component for each product type:

```
{ "rules_empty_cart__consumer_g" : {
    "LABEL" : "Empty cart - consumer g",
    "PLUGIN" : "reaction rule",
    "OWNER" : "rules",
    "REQUIRES" : [ "rules", "rules_conditional", "commerce_cart", "commerce_order" ],
    "ON" : { "commerce_cart_product_prepare" : [] },
    "IF" : [
      { "data_is" : { "data" : [ "commerce-product:type" ], "value" : "store_item" } }
    ],
    "DO" : [
      { "CONDITIONAL" : [
          {
            "IF" : { "commerce_order_contains_product_type" : {
                "commerce_order" : [ "commerce_order" ],
                "product_type" : { "value" : {
                    "product" : "product",
                    "book" : "book",
                    "food" : "food"
                  }
                },
                "operator" : "\u003E=",
                "value" : "1"
              }
            },
            "DO" : [
              { "commerce_cart_empty" : { "commerce_order" : [ "commerce_order" ] } },
              { "drupal_message" : { "message" : "cart cleared!" } }
            ]
          }
        ]
      }
    ]
  }
}

```

What this does is it every time an item is to be added to cart it checks if there at least one item in the cart that is not of the same product-type as the product that is about to be added. If there is, the cart is cleared before the item is added, if not the cart remains unchanged and the new item added to the existing list on the cart.

For this check to happen irrespective of the type, a similar rule is created per product type.

---
Tags: commerce
---


title: Implement a reset button per facet

text:
# Question
Title: Implement a reset button per facet
I'm using Search API with Facets and a view to display the results. Everything works as expected but I would like to have a reset button per facet, that could be used as a "*Show all*" button.
For the moment I'm using `facets_preprocess_facets_item_list(&$variables)` to create an extra item on the top of every list, eg.

* Facet 1 : Region
All regions, Region 1, Region 2, ...
* Facet 2 : Financial support
All financial supports, Financial support 1, Financial support 2, ...
* Facet 3 : Status
All statuses, Status 1, Status 2, ...
* Facet 4 : Sector
All sectors, Sector 1, Sector 2, ...

To construct the "*All ...*" links, I'm getting the parameters of the current page and I clean up the filters. For example if the user clicks on the "*All financial supports*" \[facet 2\] link while the current page parameters are
`../organizations?[facet 1]organizations%5B0%5D=region%3A18&[facet 2]organizations%5B1%5D=financial_support%3A1&[facet 3]organizations%5B2%5D=status%3A10&[facet 4]organizations%5B3%5D=sector%3A28`
the parameters become
`../organizations?[facet 1]organizations%5B0%5D=region%3A18&[facet 2][facet 3]organizations%5B2%5D=status%3A10&[facet 4]organizations%5B3%5D=sector%3A28`
It works, but I'm not conviced that this is the best solution because I've managed to dramaticaly slow down the display of the view and, well... it's not very elegant.
Do you know if there is another, more Drupalish solution to implement a reset button per facet? Thank you in advance for your help.

# Answer
> 1 votes
Have you tried the following?

1. Navigate to the facet setting page (`/admin/config/search/facets/facet_name/edit`)
2. under `widget` set it to `List of Checkboxes` or `List of Links` (not sure what you are using)
3. Within `List of Checkboxes setting` or `List of Links Setting`, there should be an option `Show Reset Link`.
4. Enabled it and it will show a `Reset Text` input box where you can add `Reset Facet` or whatever you need.
5. Apply other settings and click save.

---
Tags: 8, search
---


title: How to trim title for mobile devices?

text:
# Question
Title: How to trim title for mobile devices?
I am working with Drupal 8 website, on my view I have a list of contents. Some titles are pretty long, what is fine for teh desktop view, but for mobile version I need to trim the tite up to 30 characters and display dots (...) in the end, is there a way to do it in Drupal Views Settings ?

# Answer
> 1 votes
First I need to comment on the UX of the long titles. Is there some huge difference between your desktop and mobile users WRT the title length? If the longer titles are better for users then maybe they should be long on all devices. If there is not much lost by trimming them maybe they should be trimmed on desktops too, or simply rewritten to be shorter?

If it turns out it does make sense to have different title lengths on different browser widths you can do it by adding two Title fields in your Views, one regular with the full title, and the other trimmed:

* Rewrite results
    + Trim this field to a maximum number of characters
    + Trim only on a word boundary
    + Add "…" at the end of trimmed text

For *both* Title fields add a CSS class:

* Style settings
    + Customize field and label wrapper HTML
        - Create a CSS class

Name each class sensibly, so it's clear what they represent.

Then in your theme add the two CSS rules. Place the rule with the regular title class in the "general" part of your CSS (that usually applies to all, including narrow browser widths), and with it hide the field.

```
.mytitle--regular {
  display: none;
}

```

Place the override with both title classes inside the @media query that only applies to wider browser widths and hide it, for example, if you have a 30em breakpoint:

```
@media screen and (min-width: 30em) {
  .mytitle--trimmed {
    display: none;
  }

  .mytitle--regular {
    display: block;
  }
}

```

This will make sure that only the trimmed title is visible by default and only the regular for viewport/browser widths larger than 30em.

You can use CSS Editor to adjust the CSS if you can't access your (sub)theme.

---
Tags: views, 8
---


# Question
Title: Autocomplete textfield displays value when selected and not label
I have a textfield autocomplete field that shows a list of full user names and email addresses as designed but when a user is selected, the user id is displayed in the field; not the name and email address. This is the form element:

```
$form['people'] = [
  '#type' => 'textfield',
  '#placeholder' => t('Search by name'),
  '#autocomplete_route_name' => 'my_module.people',
];

```

This is the autocomplete handler in the controller:

```
public function handleAutocomplete(Request $request) {

  $query = $this->database->select('simplenews_subscriber', 'ss');
  $or = $query->orConditionGroup()
    ->condition('pa.address_given_name', '%' .$request->query->get('q') . '%', 'LIKE')
    ->condition('pa.address_family_name', '%' .$request->query->get('q') . '%', 'LIKE');
  $query->leftJoin('simplenews_subscriber__subscriptions', 'sss', 'sss.entity_id = ss.id');
  $query->leftJoin('profile', 'p', 'p.uid = ss.uid');
  $query->leftJoin('profile__address', 'pa', 'pa.entity_id = p.profile_id');
  $query->fields('ss', ['uid', 'mail']);
  $query->fields('pa', ['address_given_name', 'address_family_name']);
  $query->condition($or);
  $query->orderBy('address_given_name');
  $query->range(0, 10);

  $results = $query->execute()->fetchAll();

  $users = [];

  foreach ($results as $user) {
    $users[] = [
      'value' => $user->uid,
      'label' => $user->address_given_name . ' ' . $user->address_family_name . ' (' . $user->mail . ')',
    ];
  }

  return new JsonResponse($users);
}

```

The autocomplete textfield populates properly. I just want the first name, last name and email address to show after a selection has been made.

# Answer
> 0 votes
To get this working I had to create a hidden field to store the value and use a custom selectHandler applied via class.

**JavaScript File**

```
(function ($, Drupal) {

  'use strict';

  /**
   * Override drupal selectHandler function
   */
  function customSelectHandler(event, ui) {
    var valueField = $(event.target);
    if($(event.target).hasClass('MYCUSTOM-autocomplete')) {
      var valueFieldName = event.target.name+'_value';
      if($('input[name='+valueFieldName+']').length > 0) {
        valueField = $('input[name='+valueFieldName+']');
        // update the labels too
        const labels = Drupal.autocomplete.splitValues(event.target.value);
        labels.pop();
        labels.push(ui.item.label);
        event.target.value = labels.join(', ');
      }
    }
    const terms = Drupal.autocomplete.splitValues(valueField.val());
    // Remove the current input.
    terms.pop();
    // Add the selected item.
    terms.push(ui.item.value);

    valueField.val(terms.join(', '));
    // Return false to tell jQuery UI that we've filled in the value already.
    return false;
  }

  Drupal.behaviors.myCustomAutocomplete = {
    attach: function(context, settings) {
      // attach custom select handler to fields with class
      $('input.MYCUSTOM-autocomplete').autocomplete({
        select: customSelectHandler,
      });
    }
  };

})(jQuery, Drupal);

```

**Form PHP**

```
$form['my_field'] = array(
  '#type' => 'textfield',
  '#attributes' => ['class' => ['MYCUSTOM-autocomplete'],],
  '#autocomplete_route_name' => 'mymodule.myfield_autocomplete',
);
// field value
$form['my_field_value'] = array(
  '#type' => 'hidden',
);

```

On our forms we also have an AJAX callback on the autocompleteselect event, and I've noticed the value for the hidden field is blank but the userInput on the $form\_state has the value.

Problem with this is the splitValues function may not work well for the labels, since it appears to be comma-delimited. You may want to write your own to handle it. It also won't work well if using the same form twice on a page, but there may be a way to narrow down the selector on the hidden field.

---
Tags: 8, forms, ajax
---


# Question
Title: How can one Rewrite results of a view using a Group By
I have created a view and then added a group by a certain field. Normally one would just add a new field then rewrite the results with custom html using replacement patterns.

How would I go about this when I use group by

# Answer
> 0 votes
You can use both Rewrite and Grouping at the same time. You can Rewrite the field and use that as Group by.

If you need the same Field in the results as well as in the Group by headings, then simply add the Field twice. You can style/Rewrite them separately too.

If you want to style the grouping in a special way, or need more than one field in the Group, then you can use the `Custom text` field for advanced styling of the Group. You can see an example in this article: Control Group by styling with Custom text field

---
Tags: views
---


# Question
Title: Possible to customize the look/length of CKEditor Styles dropdown?
I've added custom styles to the Styles dropdown in CKEditor included by default in Drupal 8. They work fine. However, the dropdown isn't convenient for editors to use because

* It isn't tall enough
* There's a lot of vertical spacing between items
* Items have the style they represent, taking even more space

Here's a snip of my default Styles dropdown:

It's fine that the items have the style they represent, except it can take a lot of space in the very small box, especially if the font is large. Plus there's lots of vertical spacing between items.

I've figured a \[hackish\] way to keep the items from taking on their represented style, producing this:

But it's still too short with a lot of space between items, so only four styles of 20 show.

QUESTION:

Is there a way to customize the look of the Styles dropdown, or at least to make it longer? Lots of reading of posts and documentation hasn't provided an answer, if there is one.

# Answer
After a good bit of trial and error (I'm slow, but persistent), I've figured out the classes to modify the height and item styles in the CKEditor Styles dropdown. Here's an example using values that work for me:

```
div.cke_combopanel {
  height: 300px !important;
}
li.cke_panel_listItem a {
  padding: 3px 5px !important;
  font-size: .8em !important;
}

```

The div and li prefixes aren't required; I've included them here simply to identify the element types involved. Setting a fixed height for cke\_combopanel is an imperfect solution, but better than the short one I get by default.
> 0 votes

---
Tags: 8
---


# Question
Title: How do I change the default value of a field with AJAX?
Related to my previous question: Form fields created via Ajax are missing element attributes

I have a date field and a series of text and number fields which need their default values to change based on the value of the date field. I've updated my code so it functions this way:

```
public function buildForm(array $form, FormStateInterface $form_state) {
    $form['date'] = array(
        '#type' => 'date',
        '#ajax' => [
            'callback' => '::dateCallback',
            'wrapper' => 'wrapper',
        ],
        '#default_value' => date("Y-m-d")
    );
    $form['wrapper'] = [
        '#type' => 'container',
        '#attributes' => ['id' => 'wrapper'],
    ];

    //insert logic to determine value of a variable called $field1
    $form['wrapper']['options'] = array(
        '#type' => 'fieldset',
        '#attributes' => array('class' => array('options'))
    );
    $form['wrapper']['options']['field1'] = array(
        '#type' => 'textfield',
        '#title' => "Field 1",
        '#value' => $field1
    );
    $form['wrapper']['table'] = array(
        '#type' => 'table',
        '#title' => t('Table'),
        '#header' => array("H1", "H2", "H3"),
        '#attributes' => array('class' => array('custom-table'))
    );
    //insert logic to generate table rows
    return $form;
}

/**
 * Implements callback for Ajax event on date selection.
 *
 * @param array $form
 *   From render array.
 * @param \Drupal\Core\Form\FormStateInterface $form_state
 *   Current state of form.
 *
 * @return array
 *   Date selection section of the form.
 */
public function dateCallback(array &$form, FormStateInterface $form_state) {
    return $form['wrapper'];
}

```

There are 2 problems I am having with this:

1) Implementing it in this way, such that the `#value` property is changed when the date field is changed, technically works, however if the user then chooses to modify any of the textfield values, that is not reflected in the `$form_state` object and is overridden by whatever `#value` was last set to in `buildForm()`.

2) I have also tried using `#default_value` instead, but the value in the field will not update if it already has something in it (which it usually does from the first time `#default_value` is set in `buildForm()`). I have seen some threads like this one suggesting to unset the value in `$form_state` before setting `#default_value` again, however all such suggestions are for Drupal 7 where `$form_state` is a completely different data structure.

Is there a known way to do what I am trying to accomplish?

Update: I tried method 2 again by adding `$form_state->unsetValue('field1');` before declaring `$form['wrapper']['options']['field1']`, but this did not change the behaviour.

# Answer
> 4 votes
Method 1 setting `#value` does indeed make it impossible for the user to input data.

So the method 2 setting `#default_value` is I think still the best approach. As the old trick from D7, unsetting the value in $form\_state, doesn't work anymore, you can try this one:

Create the field in a subkey, which is incremented for each request. Set the property `#tree` on the first level of the field, so you get back the field value as array `[$key => $value]`:

```
$form['wrapper']['options']['field1']['#tree'] = TRUE;

if ($form_state->hasValue('field1')) {
  $key = key($form_state->getValue('field1'));
  $value_field1 = current($form_state->getValue('field1'));
  $key++;
}
else {
  $key = '0';
  $value_field1 = NULL;
}

// insert logic to determine new field value
// but check, if there is user input in $value_field1, that you don't want to overwrite

$form['wrapper']['options']['field1'][$key] = [
  '#type' => 'textfield',
  '#title' => 'Text 1',
  '#default_value' => $value_field1,
];

```

# Answer
> 1 votes
There is another way to do the same: Set #value property on ajax callback.

```
    <?php

    namespace Drupal\drupal_miseries\Form;

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

    class AjaxResponse extends FormBase {
      protected $ts_values = [
        'ts1' => [
          'values1' => [
            'id' => 1,
            'description' => 'Valor1',
            'status' => '1',
          ],
          'values2' => [
              'id' => 2,
              'description' => 'Valor2',
              'status' => 2,
          ],
        ],
      ];

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

      public function ajaxTableSelect(array &$form, FormStateInterface $form_state) {
        $element = $form_state->getTriggeringElement();
        if (isset($element) && $element['#type'] == 'checkbox') {
          $check_value = $element['#return_value'];
          $textfield_ts = $this->ts_values['ts1'][$check_value]['description'];
          $form['ts_textfield']['textfield']['#value'] = $textfield_ts;
        }

        return $form['ts_textfield'];
      }

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

        $form['ts_container'] = [
          '#type' => 'container',
          '#attributes' => ['id' => 'ts-container'],
        ];

        $header = [
          'id' => $this->t('ID'),
          'description' => $this->t('Description'),
          'status' => $this->t('Status'),
        ];

        $form['tableselect'] = [
          '#type' => 'tableselect',
          '#description' => $this->t('Test Tableselect'),
          '#header' => $header,
          '#options' => $this->ts_values['ts1'],
          '#empty' => $this->t('No values'),
          '#ajax' => [
            'callback' => [$this, 'ajaxTableSelect'],
            'wrapper' => 'ts-textfield',
          ],
        ];

        $form['ts_textfield'] = [
          '#type' => 'container',
          '#attributes' => ['id' => 'ts-textfield'],
        ];

        $form['ts_textfield']['textfield'] = [
          '#type' => 'textfield',
          '#description' => $this->t('Value fill by ajax'),
          '#title' => $this->t('Ajax Textfield'),
        ];

        $form['actions'] = [
          '#type' => 'actions',
        ];

        $form['action']['submit'] = [
          '#type' => 'submit',
          '#value' => $this->t('Submit'),
        ];

        return $form;
      }

      public function submitForm(array &$form, FormStateInterface $form_state) {
        dpm($form_state->getValue('tableselect'));
        dpm($form_state->getValue('textfield'));
      }
    }

```

When you click on any tableselect checkbox, textfield is set with checkbox value =\> if you click 'submit' checkbox value is assigned to textfield.

When you click on any tableselect checkbox, textfield is set with checkbox value =\> if you change textfield manually and click 'submit' new value will be assigned to textfield.

but.......Is this the correct way to do that?

# Answer
> -1 votes
A solution to append a default value to the field after callback but with option for user to change input:

add the value to field attributes: *'#attributes' =\> array('value' =\> array($form\_state-\>getValue('option2'))),*

```
        $o = [];
    $form['option1'] = array(
        '#type' => 'select',
        '#size' => 1,
        '#options' => ['a' => 'A', 'b' => 'B'],
        '#title' => $this->t('option 1'),
        '#required' => TRUE,
        '#ajax' => array(
            'callback' => array($this, 'next'),
            'wrapper' => 'option2',
        ),
    );

    if ($form_state->getValue('option1') == 'a') {
        $o = [1 => 'one', 2 => 'two'];
    }
    if ($form_state->getValue('option1') == 'b') {
        $o = [3 => 'three', 4 => 'four'];
    }

    $form['option2'] = array(
        '#type' => 'select',
        '#size' => 1,
        '#options' => $o,
        '#title' => t('option 2'),
        '#required' => TRUE,
        '#prefix' => "<div id='option2'",
        '#suffix' => '</div>',
        '#ajax' => array(
            'callback' => array($this, 'get_data'),
            'wrapper' => 'data',
        ),
    );

    $form['data'] = [
        '#type' => 'textfield',
        '#id' => 'test',
        '#title' => t("choice") . " " . $form_state->getValue('option2'),
        '#default_value' => $form_state->getValue('option2'),
        '#size' => 5,
        '#attributes' => array('value' => array($form_state->getValue('option2'))),
        '#prefix' => "<div id='data'",
        '#suffix' => '</div>',
    ];

    $form['actions']['submit'] = array(
        '#type' => 'submit',
        '#value' => $this->t('Test'),
        '#suffix' => ''
    );

    return $form;
}

/**
 * callback functions
 */
public function next(array &$form, FormStateInterface $form_state) {
    return $form['option2'];
}

public function get_data(array &$form, FormStateInterface $form_state) {
    return $form['data'];
}

public function validateForm(array &$form, FormStateInterface $form_state) {

}

public function submitForm(array &$form, FormStateInterface $form_state) {
    dpm($form_state->getValue('data'));
}

```

# Answer
> -1 votes
I've solved this by using the AJAX callback to reload the page, rather than return the form. For example:

```
$path = '/path/to/form';
$response = new AjaxResponse();
$response->addCommand(new RedirectCommand($path));
return $response;

```

It's slower than returning the form, but is a lot less code, especially if you're talking about a complex form with a lot of default values.

---
Tags: 8, forms
---


# Question
Title: How to modify a form to have some field surrounded by 'Details'?
I created a custom content entity with Drupal Console.
Three of its fields are defined this way:

```
// ----------------------------------------------------------------------------
    $weight++;
    $fields['picture'] = BaseFieldDefinition::create('image')
      ->setLabel(t('Picture'))
      ->setSettings([
        'file_extensions' => 'gif jpeg jpg png',
        'file_directory' => 'sel',
        'alt_field_required' => 0,
      ])
      ->setCardinality(3)
      ->setDisplayOptions('view', [
        'type' => 'default',
        'weight' => $weight,
      ])
      ->setDisplayOptions('form', [
        'type' => 'image_image',
        'weight' => $weight,
      ])
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE);
// ----------------------------------------------------------------------------
    $weight++;
    $fields['file'] = BaseFieldDefinition::create('file')
      ->setLabel(t('File'))
      ->setSettings([
        'file_extensions' => 'pdf',
        'file_directory' => 'sel',
        'description_field' => TRUE,
      ])
      ->setDisplayOptions('view', [
        'type' => 'file',
        'weight' => $weight,
      ])
      ->setDisplayOptions('form', [
        'type' => 'file',
        'weight' => $weight,
      ])
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE);
// ----------------------------------------------------------------------------
    $weight++;
    $fields['link'] = BaseFieldDefinition::create('link')
      ->setLabel(t('Link'))
      ->setDisplayOptions('view', [
        'type' => 'link',
        'weight' => $weight,
      ])
      ->setDisplayOptions('form', [
        'type' => 'link_default',
        'weight' => $weight,
      ])
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE);
// ----------------------------------------------------------------------------

```

And the corresponding form looks like this:
I would like to have the 'file' and the 'link' field in something like the 'Picture' field...
I updated `buildForm` :

```
public function buildForm(array $form, FormStateInterface $form_state)
  {
    $form = parent::buildForm($form, $form_state);
    $entity = $this->entity;
    $form['link']['widget']['0']['#type'] = 'details';
    return $form;
  }

```

And I got this:

How can I do the same for the 'File' field (have it surrounded in some 'Details')?

# Answer
I did it this way (thanks to @4K4 to put me on the right direction):

```
$form['fileDetails'] = array(
  '#type' => 'details',
  '#title' => $this->t('File'),
  '#weight' => 8,
);
$form['file']['#group'] = 'fileDetails';

$form['link']['widget']['0']['#type'] = 'details';

```

And I get this:
> 1 votes

---
Tags: 8, forms
---


# Question
Title: Unable to load css files using ['#attached'] or drupal_add_css
I'm attempting to attach several css files to a Drupal 7 module. All files have identical read/write/execute and owner permissions. I haven't had trouble with one of the three files but I can't get the other two added (checked the loaded stylesheets in developer tools). Here's what I've tried:

```
<?php
function usspd_search_main_form($form, $form_state) {
  $form['#attached']['css']['css1'] = '/sites/all/libraries/data_search/bootstrap_tagsinput/bootstrap_tagsinput.css'; //failed
  $form['#attached']['css']['css2'] = '/sites/all/libraries/data_search/tagme/tagme_jquery-ui.css'; //failed
  drupal_add_css('/sites/all/libraries/data_search/bootstrap_tagsinput/bootstrap_tagsinput.css'); //failed
  drupal_add_css('/sites/all/libraries/data_search/tagme/tagme_jquery-ui.css'); //failed

  $form['#attached']['css']['css3'] = drupal_get_path('module', 'usspd_search') . '/theme/usspd_search.css'; //works
  return $form;
}

```

My best guess is that there's a class conflict and instead of overriding, the attachment just fails. Is there any way to declare priority? Otherwise I'll have to add the css from both files inline.

Additionally, I'm able to call everything fine when added as raw HTML to a basic page. It shouldn't be a pathing issue.

```
<link rel="stylesheet" href="/sites/all/libraries/data_search/bootstrap_tagsinput/bootstrap_tagsinput.css">
<link rel="stylesheet" href="/sites/all/libraries/data_search/tagme/tagme_jquery-ui.css">

```

# Answer
The pathing was wrong after all. The preceding "/" was messing things up. Strangely, this was not an issue for javascript attachments. For example:

```
$form['#attached']['css']['css2'] = '/sites/all/libraries/data_search/tagme/tagme_jquery-ui.css'; //fails
$form['#attached']['js']['js2'] = '/sites/all/libraries/data_search/tagme/tagme_jquery-ui.min.js'; //works
$form['#attached']['css']['css2'] = 'sites/all/libraries/data_search/tagme/tagme_jquery-ui.css'; //works

```
> 1 votes

---
Tags: 7, theming
---


# Question
Title: Fetch view results from mymodule_preprocess_page hook
We have a View page that is coming from `myview`. Using the `header` setting in the view we have added `@total results` already, which displays in the `views-view--myview--page-1.html.twig` using the `{{ header }}` variable.

We want to be able to fetch the view results within our `mymodule_preprocess_page()` hook. On the View page, we added facet blocks that will return a list of checkboxes (this is from the Article's category tag).

**Issue**

When we modify the facet value to some value such as `value1`, the `ksm($view->total_results)` returns `NULL` value.

**Questions:**

1. How would i fetch the results using `mymodule_preprocess_page()` hook?
2. Is there a way to do it without running a query within `mymodule_preprocess_page()` hook?

**View Setup**

Display: `page`

**Format**

* unformatted list
* rendered entity | "my\_view\_mode"

**Filter criteria**

* published = true
* content type = article

**Header**

* Global: result summary (global: result summary)

**Other** \- Machine name: page\_1 \- Use Ajax = yes

What we tried:

```
function mymodule_preprocess_page($variables) {
  $view_id = \Drupal::routeMatch()->getParameter('view_id');
  $display_id = \Drupal::routeMatch()->getParameter('display_id');

  if($view_id == 'myviewId' && $display_id = 'page_1') {
    // first check we are on view page.
    $view = \Drupal\views\Views::getView($view_id);
    ksm($view->total_results); // returns null.
  }
}

```

# Answer
> 4 votes
The easiest way would be to execute the View again in the page preprocess hook.

If you want to avoid executing the View twice the task is getting a bit more tricky. This is because in D8 page elements are not necessarily rendered downstream in the order you expect. The element could have been cached in a previous request or in case the element doesn't qualify for caching it could have automatically been placeholdered and the page has been built without it, postponing the rendering until the cached page is finally delivered.

In Drupal 8 elements often need to send information upstream despite being cached or placeholdered, like cache tags or libraries. The mechanism for this is bubbleable metadata. You can use this for other things, too. See for example Add an attribute to $variables from a Controller

In case of the views results you can try this:

```
/**
 * Implements hook_views_pre_render().
 */
function mymodule_views_pre_render($view) {
  if (isset($view) && ($view->id() == 'my_view')) {
    $view->element['#attached']['placeholders']['<div id="my-view-results"></div>']['#markup'] =
      '<div id="my-view-results">' . $view->total_rows . '</div>';
  }
}

```

Place the empty div container somewhere on the page, for example in the body field of a custom block or directly in page.html.twig:

```
<div id="my-view-results"></div>

```

**AJAX**

When you enable AJAX the code above only works for the first page load. To update the results when the View gets refreshed via AJAX add your own command in a response event subscriber.

Getting the executed View then is straightforward, Views AJAX implementation keeps it in the response, so that you can use it when altering the response, see ViewAjaxResponse::getView.

*/src/EventSubscriber/ViewAjaxResponseSubscriber.php*

```
<?php

namespace Drupal\mymodule\EventSubscriber;

use Drupal\views\Ajax\ViewAjaxResponse;
use Drupal\Core\Ajax\HtmlCommand;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;

/**
 * Response subscriber to handle View AJAX responses.
 */
class ViewAjaxResponseSubscriber implements EventSubscriberInterface {

  /**
   * Adds an AJAX command to ViewAjaxResponse.
   */
  public function onResponse(FilterResponseEvent $event) {
    $response = $event->getResponse();
    if ($response instanceof ViewAjaxResponse) {
      $view = $response->getView();
      if (isset($view) && ($view->id() == 'my_view')) {
        $response->addCommand(new HtmlCommand('#my-view-results', $view->total_rows));
      }
    }
  }

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents() {
    $events[KernelEvents::RESPONSE][] = ['onResponse'];
    return $events;
  }

}

```

*mymodule.services.yml*

```
services:
  mymodule.view_ajax_response_subscriber:
    class: Drupal\mymodule\EventSubscriber\ViewAjaxResponseSubscriber
    tags:
      - { name: event_subscriber }

```

# Answer
> 1 votes
`Views::getView` is just a shortcut to loading the entity via the usual methods - it doesn't execute the View, so you won't see any results with the object you have.

I'm not sure there's an elegant way to do what you need (although I hope I'm wrong, it seems like there would be). One simple-ish workaround would be to hook into the View's build process after its execution, stash the data you need somewhere, then pick it up in the page preprocess hook.

A service seems like as a good a place as any for the storage; that might look something like this:

*mymodule/src/CurrentPageView.php*

```
namespace Drupal\mymodule;

use Drupal\views\ViewExecutable;

class CurrentPageView {

    $view = NULL;

    public function getView() {
      return $this->view;
    }

    public function setView(ViewExecutable $view) {
      $this->view = $view;
    }

}

```

(with the appropriate entry in mymodule.services.yml)

Then in `hook_views_post_execute()` stash the View:

```
function mymodule_views_post_execute(\Drupal\views\ViewExecutable $view) {
  if ($view->id() == 'myviewId') && $view->current_display == 'page_1') {
    \Drupal::service('mymodule.currentpageview')->setView($view);
  }
}

```

And pick it up again in the preprocess:

```
function mymodule_preprocess_page($variables) {
  $view_id = \Drupal::routeMatch()->getParameter('view_id');
  $display_id = \Drupal::routeMatch()->getParameter('display_id');

  if($view_id == 'myviewId' && $display_id = 'page_1') {
    // first check we are on view page.
    $view = \Drupal::service('mymodule.currentpageview')->getView();
    ksm($view->total_results);
  }
}

```

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