Como posso saber em qual botão foi clicado?

12

Eu tenho um formulário com os botões "Enviar" e "Cancelar". Em hook_submit(), como sei em que botão foi clicado?

user1359
fonte
Você está falando hook_submit()ou é um manipulador de envio de formulários? Um manipulador de envio de formulário não é a implementação de hook_submit().
kiamlaluno

Respostas:

23

Você deve usar o triggering_elementde $form_state['triggering_element'].

A melhor prática é definir um #nameatributo para o seu botão, para que você possa ter esse valor no triggering_element.

Por exemplo:

$form['delete'] = array(
  '#type' => 'submit',
  '#value' => t('Delete'),
  '#name' => 'delete',
);

Se você não definir esse atributo triggering_element, os botões serão pressionados #value(o texto que o usuário pode ler), mas isso é desencorajado, pois outros módulos podem alterar esse valor ou serem alterados pela localização.

Você também pode usar $form_state['clicked_button'], mas isso foi preterido .

Você pode ler mais informações na página de documentação da função drupal_build_form .

sanzante
fonte
7

$form_state['clicked_button']['#value'] dirá qual botão foi clicado no formulário.

iStryker
fonte
$form_state['clicked_button']['#value']:)
user1359
1
Eu gostaria de acrescentar que, se você tiver exigido campos no seu formulário e eles não estiverem preenchidos, o Drupal lançará um erro de validação do formulário (o form_submit é chamado após form_validate). Você precisa fazer algo parecido com isto devengineering.com/best-practices/drupal/…
iStryker
Este é um bom ponto!
precisa saber é o seguinte
5
Embora o "clicked_button" ainda funcione, ele foi descontinuado no D7 e a recomendação é usar o "triggering_element". Lembro que havia alguns bugs #ajax (acho) que afetavam apenas o código que usava "clicked_button", então esse é mais um motivo para usar "triggering_element". E, afinal, é apenas uma chave diferente em $ form_state.
Bojan Zivanovic
1
Embora essa abordagem funcione, ela é preterida e propensa a problemas. Veja a resposta da túnica para saber como Drupal 7 está correto.
precisa
3

Compare esses valores no que $form_statevenho fazendo no Drupal 6 e seria o mesmo no Drupal7

if($form_state['values']['ok'] == $form_state]['clicked_button']['#value']){
    //Process if OK is pressed
}else if($form_state['values']['cancel'] == $form_state]['clicked_button']['#value']) {
    //Process if Cancel is pressed
}
Shoaib Nawaz
fonte
Se eu me lembro do Drupal correto 6 $ form_state] ['X'] agora é $ form_state ['X'] no Drupal 7
iStryker
Por que você precisa comparar esses dois valores?
IStryker
Se o formulário contiver vários botões de envio. Essa comparação ajudará a diferenciar qual botão usado para enviar o formulário em um único manipulador de envio. $ form_state ['clicked_button'] ['# value'] = t ('Yes') resultará em valores diferentes na configuração multilíngue.
precisa
Uma comparação única é melhor para evitar todas as comparações de idiomas na configuração multilíngue. :)
Shoaib Nawaz
1
@ iStryker Não sei o que você quer dizer com seu primeiro comentário.
kiamlaluno
3

Nomeie os botões com o #nameatributo, assim:

$form['delete'] = array(
    '#type' => 'submit',
    '#value' => t('Delete'),
    '#name' => 'delete',
);

e então use:

$values = $form_state['input'];
if (isset($values['delete'])) // 'delete' button was pressed.
user13097
fonte
Portanto, para um formulário com dois botões de envio como este: $ form ['submit'] = array ('#type' => 'submit', '#name' => 'submit-1', '#value' => t ('Submit1'),); $ form ['submit2'] = array ('#type' => 'submit', '#name' => 'submit-2', '#value' => t ('Submit2'),); Nós apenas temos que verificar $ form_state-> getTriggeringElement () ['# name'] na função submitForm ()?
Caio
3

ATUALIZAÇÃO 2016 Drupal 8

Para aqueles que ainda estão tentando descobrir como acessar o evento acionado, aqui está a solução Drupal 8.

$form_state->getTriggeringElement()

Isso retorna a matriz do elemento de envio acionador. Se você adicionar uma marcação chamada #name, poderá acessá-la da seguinte maneira.

$button_clicked = $form_state->getTriggeringElement()['#name']

A razão por trás dessa alteração é que FormStateInterfaceagora é um readOnlyarquivo no qual apenas as classes que se estendem FormStateInterfacepodem acessar as variáveis. Então você tem que usar métodos acessadores como getTriggeringElement()para acessar a variável.

Neoaptt
fonte
Eu tenho uma atualização para o Drupal 8.4.4 em 2018: drupal.stackexchange.com/a/256112/1441
user1359
0

No Drupal 8.4.4, $form_state->getTriggeringElement()['#name'];você obtém o valor de op. Ao procurar essa chave na matriz de valores do estado do formulário, você obtém a #valuechave do elemento de formulário do botão - em outras palavras, a sequência que os usuários finais veem no botão da página.

Não sei se $form_state->getValues()['op']é universal para todos os formulários, mas estou codificando-o no formulário do meu módulo.

user1359
fonte
0

Drupal 8.6.7

Botão Criar algo como abaixo.

$form['my_button'] = [
    '#type' => 'button',
    '#value' => t('Custom Button'),
    '#name' => t('customButton'),
    '#weight' => 0,
    '#attributes' => [
      'class' => ['populate-bib-button', 'btn', 'btn-primary'],
    ],
  ];

Na sua função de envio, obtenha o nome do botão como no código abaixo.

$input = $form_state->getUserInput();
print $input['_triggering_element_name']; // customButton

A comparação pode ser feita como

if ($input['_triggering_element_name'] == 'customButton') {
  // Do something.
}

# Drupal8

Yogesh Kushwaha
fonte