Alterar um formulário existente


12

Começamos com o Drupal 8 e rapidamente encontramos nosso primeiro problema.

Como devo alterar um formulário existente no Drupal 8?

Precisamos alterar o método save do formulário do nó para redirecionar para outra página. Queremos alterar o formulário do nó para se tornar algo como um formulário de várias etapas. Depois que o usuário cria um novo conteúdo, ele é redirecionado para um novo formulário (criado) para obter mais informações.

Resolvemos nosso problema de implementação hook_entity_type_alter().

function mymodule_entity_type_alter(&$entity_info) {
  $handlers = $entity_info['node']->get('handlers');
  $handlers['form']['default'] =    'Drupal\mymodule\Form\MyExtendedNodeForm';
  $handlers['form']['edit'] = 'Drupal\mymodule\Form\MyExtendedNodeForm';
  $entity_info['node']->set('handlers', $handlers);
}

Em seguida, criamos uma nova classe de formulário que estende o formulário do nó e altera o método save.

class MyExtendedNodeForm extends NodeForm {

    public function save(array $form, FormStateInterface $form_state) {
      parent::save($form, $form_state);
      $node = $this->entity;
      $form_state->setRedirect('entity.regions.add_form', ['nid' => $node->id()]);
  }

}

Isso funciona perfeitamente, mas é bom? Se outro módulo fizer o mesmo, nosso código não será mais executado.


2
O Drupal 8 ainda suporta hook_form_alter(). Se você precisar apenas redirecionar o formulário, basta adicionar um manipulador de envio de formulários que faça o redirecionamento.
kiamlaluno

@kiamlaluno Essa deve ser a resposta que eu acho :)
Berdir

@Berdir Isso por si só não seria muito útil, receio: meu conhecimento do Drupal 8 é bastante limitado. Além disso, o OP deve deixar claro o que "alterar o save()método" realmente significa. Significa alterar a maneira como os dados são salvos ou apenas redirecionar? No primeiro caso, a resposta é mais complexa.
kiamlaluno

@kiamlaluno Thx pela resposta. Nesse caso, precisamos apenas redirecionar após o save () para que sua resposta funcione. Mas eu também estava interessado em como alterar outras coisas no formulário da maneira correta do Drupal 8. Por exemplo mudança como ele está salvo, ou adicionar campos ao formulário .. etc ..
Jens Steppe

Respostas:


4

Eu tive que fazer exatamente a mesma coisa ontem, e ainda estou procurando uma maneira mais Drupal 8 de fazer isso, mas não a encontrei. Acabei fazendo assim:

<?php

/**
 * @file
 * This is my module.
 */

use Drupal\Core\Form\FormStateInterface;
use Symfony\Component\HttpFoundation\Request;

/**
 * Implements hook_form_alter().
 */
function MODULE_form_alter(array &$form, FormStateInterface $form_state, $form_id) {
  if ($form_id == 'user_form') {
    $form['actions']['submit']['#submit'][] = '_MODULE_goto';
  }
}

/**
 * Make the form go to route.id.
 */
function _MODULE_goto($form, FormStateInterface $form_state) {
  $form_state->setRedirect('route.id');
}

Ainda estou muito interessado em fazê-lo de uma maneira diferente, meu módulo parecia tão limpo sem o arquivo .module :).


3

Estou usando o Drupal 8.1.1 e estava tentando redirecionar os usuários depois que eles modificaram sua conta, ou seja, clicando no botão Salvar na página / user / edit. Inicialmente, tentei o seguinte:

/**
 * Implements hook_form_alter().
*/
function MODULE_form_alter(array &$form, FormStateInterface $form_state, $form_id) {
  if ($form_id == 'user_form') {
    $form['#submit'][] = '_MODULE_goto';
  }
}

Embora isso funcionasse para o user_login_form, não funcionaria user_form. Pois user_formeu tive que usar

$form['actions']['submit']['#submit'][] = '_MODULE_goto';

Espero que ajude outras pessoas que tropeçam no mesmo problema!


1

Bem, eu queria alterar o site_information_settingsformulário para adicionar alguns campos.

Como você, eu tive escolha entre

  • hook_form_alter(ou hook_form_FORM_ID_alter)
  • estender a classe do formulário original

Queria fazer algum OOP, então comecei a escrever um serviço de assinante de rota alterando o atributo system.site_information_settingsda rota _form.

Então, na minha nova classe estendendo o SiteInformationForm, depois que os campos e seus validadores foram adicionados e a função de envio estendida, senti exatamente da mesma maneira que você ... Agora, e se outro módulo reescrever a rota do formulário, para usar sua própria classe?

De volta ao começo, eu tinha escolha entre duas opções ... parece que eu escolhi a errada.

hook_form_alter/ hook_form_FORM_ID_alterparece ser a melhor maneira de alterar um formulário existente.


0

Parece com o que você deseja fazer, não para realmente alterar o método save, mas para alterar o redirecionamento quando um nó é salvo.

Nessa situação, fazer como o Drupal 7, hook_form_alterjuntamente com um manipulador de envio personalizado (no formulário ou no botão, dependendo do formulário e do requisito) seria uma boa solução.

O que você descreve na pergunta também funciona, mas evitaria sobrescrever a classe base, a menos que eu realmente queira alterar algo na classe.

O método save usa apenas como manipulador de envio, portanto, não faz muito sentido sobrescrever apenas para adicionar um redirecionamento.


0

Acho que o melhor método é ainda usar um dos ganchos da família form_alter, anexar um manipulador de envio e, dentro desse conjunto, redirecionar.

Contrib estender classes base para fazer isso é cabeludo na minha opinião. Especialmente porque nenhuma função está mudando, apenas redirecionando.


0

Você pode criar um novo EventSubscriber que escute o evento KernelEvents :: REQUEST e, em seguida, reagir ao enviar um formulário de nó, algo como isto

Enfim, a maneira hook_form_alter funciona ok.


0

O que eu encontrei até agora: Implementar um formulário alter hook e tentar alterar os manipuladores de validação / envio no formulário alter hook em si só funcionará se você alterar os manipuladores $ form ['# validate] / $ form [#submit']. (chamar funções form_state para isso não funcionará no formulário alter hook propriamente dito)

Mas quando você tenta fazer isso dentro de um manipulador de validação, ele tende a funcionar:

// Load form submit handlers.
$submit_handlers = $form_state->getSubmitHandlers();

// Drop the core entity submitForm function.
$key_core_submit = array_search('::submitForm', $submit_handlers);
if ($key_core_submit !== FALSE) {
  unset($submit_handlers[$key_core_submit]);
  // Add your own submit handler.
  array_unshift($submit_handlers, 'yourmodule_submit_handler');
}
// Update submit handlers.
$form_state->setSubmitHandlers($submit_handlers);

Isso ocorre porque o formulário agora foi criado completamente, e não o caso no formulário que altera o próprio gancho.

A ideia é: você pode adicionar um manipulador de validação como o último, avaliar outros manipuladores existentes para o envio e alterá-los ali mesmo.

Se você também deseja alterar os manipuladores de validação, verifique se o seu é executado antes de qualquer outro e altere o que deseja no manipulador de validação.

Ainda procurando por uma maneira melhor, sempre preciso substituir os manipuladores de validação / envio do formulário de registro do usuário. Mas podem existir outros módulos que interrompem a implementação dos meus módulos. Portanto, meu módulo precisaria verificar isso e isso é possível dessa maneira. Eu me pergunto se alguma forma de entidade após a função de compilação existe para fazer isso. (algo que é executado quando o formulário é preenchido e está prestes a ser entregue) (não é muito complicado para esse caso simples)

Ignorar o redirecionamento do método save () não é possível, mas a desativação do save () é feita dessa maneira (+ implemente o seu próprio). É verdade que uma classe é mais agradável e oferece acesso mais fácil a objetos / etc, mas a substituição de uma classe principal realmente leva a problemas quando outros módulos desejam usá-los. Esse não é o caso se você usar esse código.


0

Depois de verificar esse problema, descobri que é adequado ao seu caso:

/**
 * Implements hook_entity_type_alter().
 */
function mymodule_entity_type_alter(&$entity_info) {
 $entity_info['node']->setFormClass('edit','Drupal\mymodule\Form\CustomNodeForm');
}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.