Hot answers tagged

7

Yes, instead of content entities you can use config entities. But for only a few configuration options this is too much effort. In this case you can use the Simple Configuration API, either by creating your own form https://www.drupal.org/docs/drupal-apis/configuration-api/working-with-configuration-forms or by adding form values to existing admin forms in a ...


6

You just seem to be getting confused with the form build concept and PHP logic - what you need to do is add to the existing form array ($form in buildForm), not create a second separate form/array. With that in mind, this: $this->secondForm($param); Doesn't do anything. You're not merging the return value back into $form, and you're not passing $form to ...


5

Nice catch! It does nothing. You can safely remove it. Looks like some kind of forgotten relict. Ah, yeah. The same pattern can be found in core's book module: BookSettingsForm.php. And there is a 12(!) years old open issue to have it removed. [#315176] Clean-up remains of $form['array_filter'] hack with array_filter in book module


5

Provide a controller to download the PDF as discussed in the comments: https://stefvanlooveren.me/blog/serve-pdf-download-controller-drupal-8 <?php namespace Drupal\MYMODULE\Controller; use Drupal\Core\Controller\ControllerBase; use Symfony\Component\HttpFoundation\BinaryFileResponse; /** * Class PdfGeneratorController. */ class ...


5

Normally the original entity is stored in the entity object before the user input is applied. If not, you can get it via the loaded revision id, which is preserved when an entity is loaded to keep it save from changes: if (isset($entity->original)) { $original = $entity->original; } else { $original = \Drupal::entityTypeManager() ->...


4

\Drupal::formBuilder()->getForm() already returns a render array, see the FormBuilder::getForm() documentation. To render the form, you just need to pass the results of getForm() to your $build array, then render it in your template. In hook_ENTITY_TYPE_view(): function MYMODULE_node_view(array &$build, NodeInterface $node, EntityViewDisplayInterface $...


4

I finally solved this using the Require on Publish module. It offers an additional checkbox to require only when publishing the node. This module allows fields to be required only when the piece of content is being published or is already published. This can be used when you have fields such as tags or SEO information on your piece of content that editors ...


4

You have to add ajax commands to the ajax response, using the unrendered render array: $response->addCommand(new ReplaceCommand('#form-container', $renderable)); BTW you can only return a Drupal ajax response if you have triggered an ajax request via ajax.js. Outside of form submits you usually do this by adding the class use-ajax to a link. For custom ...


4

Give your submit button a unique and valid #name attribute. I don't think it will work if you put spaces in it: $form['actions']['save'] = [ '#type' => 'submit', '#name' => 'standard-save', '#value' => t('Print and Mail Check'), '#button_type' => 'primary', '#submit' => [ '_my_module_form_submit', ], ]; Submit handler function ...


3

Problem 1: Incorrect namespace. The class name should not be included in the namespace. Your namespace should be: Drupal\lookup\Form Problem 2: The name of your class is not the same name as the routing file (capitalization). Class name: lookupform Routing file: _form: '\Drupal\lookup\Form\lookupForm' (Capital F) Problem 3 (credit: laymannx) - you're ...


3

Here is how I would do it: /* * Implements hook_form_FORM_ID_alter(). */ function mymodule_form_node_quiz_edit_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) { $form['field_duration']['widget'][0]['value']['#type'] = 'hidden'; // hide field $form['field_duration']['widget'][0]['value']['#default_value'] = time(); // ...


3

From WidgetBase::form: // Most widgets need their internal structure preserved in submitted values. $elements += ['#tree' => TRUE]; When customizing the structure you also need to make sure the values get submitted correctly. For example by adding WidgetInterface::massageFormValues to your widget. A much easier way though is to keep the standard ...


3

According to the documentation: https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Render%21Element%21Select.php/class/Select #empty_option: (optional) The label to show for the first default option. By default, the label is automatically set to "- Select -" for a required field and "- None -" for an optional field.


3

For some reason dpm() fails to show #prefix & #suffix values, bug maybe? Use kint() instead. You'll need to enable the Kint module if you're using Devel 8.x-2.1. But if using Devel 4.0.1 you'll need to install kint via composer require kint-php/kint. Dump aside, Drupal automatically strips the style= for security reasons. Instead, it should be $prefix = '...


3

There are two basic problems here. First, your debug output doesn't display what you expect, and second the form is not visibly altered as you expect. dpm() displays the output in the messages area of the page. What you are trying to display is an array containing an HTML tag as one of its values - that value will be interpreted as an HTML tag when shown in ...


3

if ($form_id = 'node_hotel_edit_form') is wrong. This will assign node_hotel_edit_form to $form_id and always evaluate to TRUE. It should be if ($form_id === 'node_hotel_edit_form') or == also works.


3

I assume you're using Drupal 8. Try the below in your hook alter. This also assumes the usage of the default body field in use: use Drupal\Core\StringTranslation\TranslatableMarkup; // Ensure summary field existence. if (isset($form['body']['widget'][0]['summary'])) { $form['body']['widget'][0]['summary']['#description'] = new TranslatableMarkup('Your ...


3

I don't think you can attach multiple ajax callbacks to a form element. But you could override the callback by extending the core element: /src/Element/MyManagedFile.php <?php namespace Drupal\mymodule\Element; use Drupal\file\Element\ManagedFile; use Drupal\Core\Ajax\AlertCommand; use Drupal\Core\Form\FormStateInterface; use Symfony\Component\...


3

FormBase is abstract; it implements FormInterface, but doesn't contain methods for: getFormId buildForm submitForm You need to provide those in your class or PHP will reject it. ... class Test extends FormBase { public function getFormId() { return 'foo'; } public function buildForm(array $form, FormStateInterface $form_state) { // Build ...


3

Looks like the culprit was how I was adding the name rows to the form. Wrong: $form['names'][] = $row; Correct: $form['names'][$key] = $row; The reason it was "working" after the first submit, was that the replaced form had appended token id's to the form, so the replacement could not occur on the #testform id, as it no longer existed. Here's ...


2

Extending Clive answer. You can use hook_element_info_alter to call always the custom process function: /** * Implements hook_element_info_alter(). * * @param $type */ function MYMODULE_element_info_alter(&$type) { // Custom process managed_file element. $type['managed_file']['#process'][] = 'MYMODULE_file_managed_file_process'; } /** * @...


2

There is a big gotcha with the search form. The answer with the themename_search only works if the search block is enabled or disabled and has never been removed in /admin/structure/block. If in /admin/structure/block you re-add/place it again, the search form ID changes to formsearch. It no longer uses the theme name! And again it only works if this block ...


2

A working code example for this is the No Current Password module. Here's the relevant code: /** * Implements hook_form_FORM_ID_alter(). * Remove the current password field from the user_profile_form form (user/%/edit). */ function nocurrent_pass_form_user_form_alter(&$form, &$form_state) { // Get the module's configuration $config = \Drupal:...


2

The accepted answer doesn't check form mode, but it checks the operation instead. To validate on form mode, you can use something like this: function mymodule_form_FORM_ID_alter(&$form, FormStateInterface $form_state) { /** @var \Drupal\Core\Entity\Entity\EntityFormDisplay $formDisplay */ $formDisplay = $form_state->getStorage()['form_display']; ...


2

I would like to suggest is, use hook_form_alter, create an ajax handler on value change on select list, disable ( remove) submit button. /** * Implements hook_form_alter(). */ function YOURMODULENAME_form_alter(&$form, FormStateInterface $form_state, $form_id) { if ($form_id == 'YOUR_FORM_ID') { $form['YOUR_FIELD_MACHINE_NAME']['#ajax'] = [ ...


2

And Just as a Reference, another solution is using the #disabled attribute: function mymodule_form_alter(&$form, &$form_state, $form_id) { if ($form_id == 'user_register_form') { $form['field_name']['#disabled'] = TRUE; } }


2

This is not working, you can't use a form template in a controller. You have to assign the template to $form['#theme'] when building the form or in a form alter hook. Then it gets used by formBuilder()->getForm() automatically. See for example seven_form_node_form_alter(): $form['#theme'] = ['node_edit_form']; and the corresponding twig file for a two ...


2

Create a .module in your module folder ex : library_assets/library_assets.module in the .module file use this HOOK to create a new form suggestion that will be dynamically equal to form--{form-id}.html.twig <?php /** 1. Implement {module_name}_theme_suggestions_form_alter */ function library_assets_theme_suggestions_form_alter(array &$...


2

Use instead of #theme a form element #type: '#type' => 'table' The table form element has an extra step for processing when used in a form. You don't need '#rows'. Any array key not starting with #, also the index added automatically by appending a row with [], is considered to be a renderable child and displayed as row.


2

In some cases it may be preferable for your configuration to actually be stored as content, you may not want it managed as part of the configuration system and/or it may be easier to work with if it's content. In those cases, the Config Pages module is great. From the module's Do I need it section: At some point I was tired of creating custom pages using ...


Only top voted, non community-wiki answers of a minimum length are eligible