Estou tentando permitir que o usuário escolha dinamicamente vários campos com base em uma caixa suspensa usando uma chamada ajax, mas não consigo receber a chamada ajax para reconstruir o formulário posteriormente.
<?php
class AJAXexample extends BlockBase {
public function blockForm($form, FormStateInterface $form_state) {
if (empty($form_state->getValue('number'))) {
$form_state->setValue('number', 3);
}
$form['columnNum'] = [
'#title' => t('Number of Columns'),
'#type' => 'select',
'#options' => [
1 => '1',
2 => '2',
3 => '3',
4 => '4',
],
'#default_value' => $this->configuration['columnNum'],
'#empty_option' => t('-select-'),
'#ajax' => [
'callback' => [$this, 'columnCallback'],
],
];
for ($i = 0; $i < $form_state->getValue('number'); $i += 1) {
$form['column'][$i] = [
$i => [
'#type' => 'details',
'#title' => t('Column '.$numTitle),
'#open' => FALSE,
'columnTitle' => [
'#type' => 'textfield',
'#title' => t('Column Title'),
'#value' => $config[0]['columnTitle'],
],
],
];
return $form;
}
public function columnCallback(array &$form, FormStateInterface $form_state) {
$form_state->setValue('number', 10);
$form_state->setRebuild(true);
return $form;
}
}
O número de campos de texto é baseado na variável form_state 'number'. O retorno de chamada columnCallback altera a variável form_state para 10 e é acionado quando o campo de formulário 'columnNum' é alterado. No entanto, o formulário não é reconstruído com o novo número de campos, apesar de $ form_state-> setRebuild (); é chamado. Existe uma maneira de obter o formulário para reconstruir após uma chamada de ajax?
NOTA: Eu já tentei técnicas como substituir ou anexar os itens do formulário dentro da chamada ajax real, mas quando isso acontece, nenhuma das entradas nos campos substituídos é passada para $ form_state.
ATUALIZAÇÃO: Depois de tentar a solução do 4k4, recebo um erro
Recoverable fatal error: Argument 1 passed to Drupal\Core\Render\MainContent\AjaxRenderer::renderResponse() must be of the type array, null given, called in /Library/WebServer/Documents/aaep/web/core/lib/Drupal/Core/Form/FormAjaxResponseBuilder.php on line 89 and defined in Drupal\Core\Render\MainContent\AjaxRenderer->renderResponse() (line 45 of /Library/WebServer/Documents/aaep/web/core/lib/Drupal/Core/Render/MainContent/AjaxRenderer.php).
A crença é que o erro ocorre porque $ form ['column'] está retornando nulo, apesar de ter sido criado como um contêiner na função blockForm. Tentei ligar para o retorno de outras maneiras, como
'#ajax' => [
'callback' => '::columnCallback',
]
e
'#ajax' => [
'callback' => [$this, '\Drupal\my_examples\Plugin\Block\AJAXexample::columnCallback'],
]
Mas eu recebo o mesmo erro. Curiosamente, quando altero o retorno de chamada para retornar todo o formulário $ em vez de apenas $ form ['column'], ele repete o formulário (uma cópia do formulário aparece abaixo do formulário atual) e ainda sem o número adequado de colunas.
Respostas:
O primeiro problema é manipular o valor do número da coluna. Na primeira compilação, obtenha-a da configuração, em uma reconstrução, obtenha-a a partir da entrada do usuário e insira-a
$columnNum
.O segundo é decidir qual parte do formulário muda no AJAX e colocá-lo em um contêiner div com o ID
columns-wrapper
.No retorno de chamada, precisamos apenas retornar o wrapper ajax.
Drupal reconstrói o formulário em cada solicitação de ajax e o coloca no parâmetro
$form
do retorno de chamada. Não faria sentido tentar reconstruí-lo novamente.fonte
return $form['column']
é nulo, porque o valor de retorno é desmarcadorenderResponse()
. Ainda pode haver um problema com a lista de parâmetros do retorno de chamada, porque colocamos pelo menos um contêiner nessa chave de formulário e isso evitaria esse erro.Acho que você está perdendo o
wrapper
método no'#ajax'
(ao lado decallback
) que consiste noid
atributo HTML da área onde o conteúdo retornado pelo retorno de chamada deve ser colocado. Consulte: API do Ajax . Então você deve garantir que esse contêinerid
exista.Exemplo de código (simplificado):
Para obter um exemplo de código completo, consulte: Como adicionar mais opções para rádios de tipo, use Ajax no Drupal 8 .
fonte