ISSUE DESCRIPTION:
If you add custom field to the views menu link edit form via hook_BASE_FORM_id_alter, custom options are not saved on the form submit.
ENVIRONMENT:
OS/web server: Linux/Apache
Drupal version: 8.3.5
REPRODUCIBILITY: Always
STEPS TO REPRODUCE:
- Create a custom module (e.g. mymodule). Note that I provided compressed fully working module in the attachments.
- In the .module file add the following code in order to alter views menu link edit form, create the form submit handler and define our own views menu link class allowing options to be saved:
/**
* Implements hook_BASE_FORM_id_alter().
*
* Alter menu link edit form for special menu item type (e.g. Home).
*/
function mymodule_form_menu_link_edit_alter(&$form, &$form_state, $form_id) {
$menu_link = null;
$menu_link_definition = $form_state->getBuildInfo()['args'][0]->getPluginDefinition();
$options = $form_state->getBuildInfo()['args'][0]->getOptions();
$form['mymodule_test'] = [
'#type' => 'textfield',
'#title' => t('MyModule test field'),
'#default_value' => !empty($options['mymodule_test']) ? $options['mymodule_test'] : '',
];
$form['#submit'][] = 'mymodule_form_menu_link_edit_submit';
}
/**
* Callback for menu_link_edit form submit.
*/
function mymodule_form_menu_link_edit_submit(&$form, &$form_state) {
$menu_link_manager = \Drupal::service('plugin.manager.menu.link');
$menu_link_id = $form_state->getValue('menu_link_id');
$options = ['mymodule_test' => $form_state->getValue('mymodule_test')];
$menu_link_manager->updateDefinition($menu_link_id, ['options' => $options]);
}
/**
* Implements hook_menu_links_discovered_alter().
*/
function mymodule_menu_links_discovered_alter(&$links) {
foreach ($links as $key => $value) {
if (!empty($value['provider']) && $value['provider'] == 'views') {
if (strpos($key, 'views_view:') === 0) {
$links[$key]['class'] = 'Drupal\mymodule\MyModuleViewsMenuLink';
}
}
}
}
- Create file /src/MyModuleViewsMenuLink.php with the content below. This is the class that extends ViewsMenuLink allowing options to be saved.
<?php
namespace Drupal\mymodule;
use Drupal\views\Plugin\Menu\ViewsMenuLink;
/**
* Defines menu links provided by views.
*/
class MyModuleViewsMenuLink extends ViewsMenuLink {
/**
* {@inheritdoc}
*/
protected $overrideAllowed = [
'menu_name' => 1,
'parent' => 1,
'weight' => 1,
'expanded' => 1,
'enabled' => 1,
'title' => 1,
'description' => 1,
// MyModule: Allow override of this variable.
'options' => 1,
];
}
- When we've finished coding part it's time to create a views menu link itself. Navigate to Administration > Structure > Views > Add view
- Enter "View name" and leave "View settings" default
- Check option "Create a page" under the "Page Settings" section
- Check option "Create a menu link" and select "Main navigation" in "Menu" select list. New menu item linked to the view will be displayed in the Main navigation when you visit the front page.
- Navigate to the edit form of the "Main navigation", Administration > Structure > Menus > Edit Main navigation
- Edit the view menu item by clicking the "Edit" operation. The edit form will be displayed containing the "MyModule test field" we've defined in the alter form hook.
- Enter whatever you want in the field and save the form
EXPECTED BEHAVIOR:
Entered value in the test field will be saved in the options like in any other altered menu link edit form.
ACTUAL BEHAVIOR:
Custom options are not saved at all.
NOTES:
- The similar logic works for module-defined links without any problems (e.g. Home, Login/Logout menu items...)
- The test module also contains some other extended menu links classes but they are not relevant for views menu links (or I suppose they aren't)
Comment | File | Size | Author |
---|---|---|---|
mymodule.zip | 3.23 KB | MitraX |
Comments
Comment #2
MitraX CreditAttribution: MitraX commentedComment #3
EclipseGc CreditAttribution: EclipseGc at Acquia commentedI don't see anything that convinces me this is a plugin system level problem, so untagging it.
Super interesting use case, did you confirm your submission handler is firing? That'd be my first priority.
Eclipse