Email us at info@henrytech.org to discuss your Drupal Migration today!
In the case that you need to have a form contained in a popup/modal window, that you also need to pass a parameter to, such as a specific node or entity id. In this case we are clicking on a link in a template file to open the form, and the entity id is available in the template file that has the link. You can also put such a link in a view, and pass it an id from the view. So you can have a view with a button for each row that references the ID from that row, that has a form that does something.
In your custom-template.html.twig file:
You can pass an ID here from the node or from a preprocess function.
<a class="custom-class use-ajax" href="{{ path('your_custom_module.custom_form', {'custom_parameter': fields.id.content|render|striptags|trim }) }}"> </a>
In your custom_module.routing.yml:
your_custom_entity_type here would be the entity type of the ID you are passing, i.e, node, etc.
your_custom_module.custom_form: path: '/ajax/something/custom-form/{custom_parameter}' defaults: _controller: '\Drupal\your_custom_module\Controller\CustomController::customForm' methods: ['POST'] requirements: _access: 'TRUE' options: parameters: custom_parameter: type: entity:your_custom_entity_type
In your CustomController.php:
Here, the customForm function, referenced in the routing file, is defined, and the ajax response. We pass it the ID of the entity that we need for the form.
<?php namespace Drupal\your_custom_module\Controller; use Drupal\Core\Ajax\AjaxResponse; use Drupal\Core\Ajax\AppendCommand; use Drupal\Core\Ajax\InvokeCommand; use Drupal\Core\Ajax\RemoveCommand; use Drupal\Core\Controller\ControllerBase; use Drupal\Core\Database\Connection; use Drupal\Core\Entity\EntityFormBuilderInterface; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Form\FormBuilderInterface; use Drupal\Core\Form\FormState; use Drupal\Core\Session\AccountInterface; class CustomController extends ControllerBase { private function prepareFormResponse(int $id = 0): AjaxResponse { $response = new AjaxResponse(); $form_state = new FormState(); $form_state->addBuildInfo('args', [$id]); $form = $this->formBuilder->buildForm(CustomTrainingForm::class, $form_state); $build = [ '#theme' => 'custom_theme', '#title' => 'Your form Title', '#body' => $form, ]; $response->addCommand(new RemoveCommand('.modal-ajax')); $response->addCommand(new AppendCommand('body', $build)); $response->addCommand(new InvokeCommand('.modal-ajax', 'modal', ['show'])); return $response; } } public function customForm(EntityClass $entity): AjaxResponse { $id = (int) $entity->id(); return $this->prepareFormResponse($id); }
In your CustomForm.php:
This is the actual form that is rendered inside the modal window.
<?php namespace Drupal\your_custom_module\Form; use Drupal\Core\Ajax\AjaxResponse; use Drupal\Core\Ajax\HtmlCommand; use Drupal\Core\Ajax\InvokeCommand; use Drupal\Core\Ajax\RedirectCommand; use Drupal\Core\Ajax\AppendCommand; use Drupal\Core\Ajax\RemoveCommand; use Drupal\Core\Ajax\ReplaceCommand; class CustomForm extends FormBase { public function getFormId() { return 'custom_form_id'; } public function buildForm(array $form, FormStateInterface $form_state, int $id = 0) { $user = \Drupal::currentUser(); $form['some_users_form_field'] = array( '#type' => 'entity_autocomplete', '#title' => t('Users'), '#target_type' => 'user', '#default_value' => '', '#tags' => TRUE, '#cache' => ['contexts' => ['user']], ); // Actions. $form['actions'] = ['#type' => 'actions']; $form['actions']['submit'] = [ '#type' => 'submit', '#value' => 'Submit Form', '#ajax' => [ 'callback' => '::ajaxSubmit', ], '#attributes' => [ 'class' => ['use-ajax-submit'], ], ]; return $form; }
Comments1
Thanks, very helpful
Thank you for posting, this saved me some time.