J'essaie de permettre à l'utilisateur de choisir dynamiquement un certain nombre de champs en fonction d'une liste déroulante à l'aide d'un appel ajax, mais je n'arrive pas à obtenir l'appel ajax pour reconstruire le formulaire par la suite.
<?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;
}
}
Le nombre de champs de texte est basé sur la variable form_state 'nombre'. Le callback columnCallback change la variable form_state à 10 et est déclenché lorsque le champ de formulaire 'columnNum' est modifié. Cependant, le formulaire n'est pas reconstruit avec le nouveau nombre de champs même si $ form_state-> setRebuild (); est appelé. Existe-t-il un moyen d'obtenir le formulaire à reconstruire après un appel ajax?
Remarque: j'ai déjà essayé des techniques telles que le remplacement ou l'ajout des éléments du formulaire à l'intérieur de l'appel ajax réel, mais lorsque cela se produit, aucune entrée dans les champs remplacés n'est transmise à $ form_state.
MISE À JOUR: Après avoir essayé la solution de 4k4, je reçois une erreur
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 croyance est que l'erreur se produit car $ form ['colonne'] retourne null malgré sa création en tant que conteneur dans la fonction blockForm. J'ai essayé d'appeler le rappel par d'autres moyens comme
'#ajax' => [
'callback' => '::columnCallback',
]
et
'#ajax' => [
'callback' => [$this, '\Drupal\my_examples\Plugin\Block\AJAXexample::columnCallback'],
]
Mais je reçois la même erreur. Curieusement, lorsque je modifie le rappel pour renvoyer l'intégralité de $ form au lieu de $ form ['column'], il répète le formulaire (une copie du formulaire apparaît sous le formulaire actuel) et toujours sans le bon nombre de colonnes.
Réponses:
Le premier problème est de gérer la valeur du numéro de colonne. Sur la première version, récupérez-le dans la configuration, lors d'une reconstruction, récupérez-le dans l'entrée utilisateur et placez-le
$columnNum
.La seconde est de décider quelle partie du formulaire change dans AJAX et de le mettre dans un conteneur div avec l'id
columns-wrapper
.Dans le rappel, il suffit de renvoyer le wrapper ajax.
Drupal reconstruit le formulaire à chaque demande ajax et le place dans le paramètre
$form
du rappel. Cela n'aurait aucun sens d'essayer de le reconstruire à nouveau.la source
return $form['column']
est nul, car la valeur de retour n'est pas cochéerenderResponse()
. Cela pourrait toujours être un problème avec la liste des paramètres du rappel, car nous avons mis au moins un conteneur dans cette clé de formulaire et cela empêcherait cette erreur.Je suppose que vous manquez de
wrapper
méthode dans votre'#ajax'
(à côté decallback
) qui consiste en l'id
attribut HTML de la zone où le contenu renvoyé par le rappel doit être placé. Voir: API Ajax . Ensuite, vous devez vous assurer qu'un tel conteneurid
existe.Exemple de code (simplifié):
Pour un exemple de code complet, voir: Comment ajouter plus d'options pour les radios de type utiliser Ajax dans Drupal 8 .
la source