Estoy tratando de permitir que el usuario elija dinámicamente una cantidad de campos en función de un cuadro desplegable utilizando una llamada ajax, pero parece que no puedo obtener la llamada ajax para reconstruir el formulario después.
<?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;
}
}
El número de campos de texto se basa en la variable form_state 'número'. La devolución de llamada columnCallback cambia la variable form_state a 10 y se activa cuando se cambia el campo de formulario 'columnNum'. Sin embargo, el formulario no se reconstruye con el nuevo número de campos aunque $ form_state-> setRebuild (); se llama. ¿Hay alguna manera de hacer que el formulario se reconstruya después de una llamada ajax?
NOTA: Ya he probado técnicas como reemplazar o agregar los elementos del formulario dentro de la llamada ajax real, pero cuando eso sucede, ninguna de las entradas en los campos reemplazados se pasa a $ form_state.
ACTUALIZACIÓN: después de intentar la solución de 4k4, recibo un error
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).
La creencia es que el error ocurre porque $ form ['column'] está volviendo nulo a pesar de haber sido creado como un contenedor en la función blockForm. He intentado llamar a la devolución de llamada de otras maneras como
'#ajax' => [
'callback' => '::columnCallback',
]
y
'#ajax' => [
'callback' => [$this, '\Drupal\my_examples\Plugin\Block\AJAXexample::columnCallback'],
]
Pero recibo el mismo error. Curiosamente, cuando cambio la devolución de llamada para devolver todo el formulario $ en lugar de solo $ formulario ['columna'], repite el formulario (una copia del formulario aparece debajo del formulario actual) y aún sin el número adecuado de columnas.
Respuestas:
El primer problema es manejar el valor para el número de columna. En la primera compilación, obténgalo desde la configuración, en una reconstrucción, consígalo desde la entrada del usuario y colóquelo
$columnNum
.El segundo es decidir qué parte del formulario cambia en AJAX y poner esto en un contenedor div con la identificación
columns-wrapper
.En la devolución de llamada solo necesitamos devolver el contenedor ajax.
Drupal reconstruye el formulario en cada solicitud ajax y lo coloca en el parámetro
$form
de la devolución de llamada. No tendría sentido tratar de reconstruirlo nuevamente.fuente
return $form['column']
es nulo, porque el valor de retorno se desmarcarenderResponse()
. Todavía podría ser un problema con la lista de parámetros de la devolución de llamada, porque ponemos al menos un contenedor en esa clave de formulario y esto evitaría este error.Supongo que te falta un
wrapper
método en tu'#ajax'
(junto acallback
) que consiste en elid
atributo HTML del área donde se debe colocar el contenido devuelto por la devolución de llamada. Ver: API de Ajax . Entonces debes asegurarte de queid
exista dicho contenedor .Ejemplo de código (simplificado):
Para ver un ejemplo de código completo, consulte: Cómo agregar más opciones para radios de tipo use Ajax en Drupal 8 .
fuente