Ich versuche, dem Benutzer zu ermöglichen, mithilfe eines Ajax-Aufrufs dynamisch eine Anzahl von Feldern basierend auf einem Dropdown-Feld auszuwählen, aber ich kann den Ajax-Aufruf scheinbar nicht dazu bringen, das Formular anschließend neu zu erstellen.
<?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;
}
}
Die Anzahl der Textfelder basiert auf der form_state-Variablen 'number'. Der Rückruf columnCallback ändert die Variable form_state in 10 und wird ausgelöst, wenn das Formularfeld 'columnNum' geändert wird. Das Formular wird jedoch nicht mit der neuen Anzahl von Feldern neu erstellt, obwohl $ form_state-> setRebuild (); wird genannt. Gibt es eine Möglichkeit, das Formular nach einem Ajax-Aufruf wiederherzustellen?
ANMERKUNG: Ich habe bereits Techniken ausprobiert, wie das Ersetzen oder Anhängen der Elemente des Formulars innerhalb des eigentlichen Ajax-Aufrufs, aber wenn dies geschieht, wird keine Eingabe in die ersetzten Felder an $ form_state übergeben.
UPDATE: Nach dem Versuch, 4k4 zu lösen, erhalte ich eine Fehlermeldung
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).
Die Annahme ist, dass der Fehler auftritt, weil $ form ['column'] null zurückgibt, obwohl es in der blockForm-Funktion als Container erstellt wurde. Ich habe versucht, den Rückruf auf andere Weise wie
'#ajax' => [
'callback' => '::columnCallback',
]
und
'#ajax' => [
'callback' => [$this, '\Drupal\my_examples\Plugin\Block\AJAXexample::columnCallback'],
]
Aber ich erhalte den gleichen Fehler. Wenn ich den Rückruf ändere, um das gesamte $ form anstelle von nur $ form ['column'] zurückzugeben, wird das Formular seltsamerweise wiederholt (eine Kopie des Formulars wird unter dem aktuellen Formular angezeigt) und immer noch ohne die richtige Anzahl von Spalten.
Antworten:
Das erste Problem besteht darin, den Wert für die Spaltennummer zu behandeln. Beim ersten Build wird es aus der Konfiguration abgerufen, beim erneuten Build wird es aus der Benutzereingabe abgerufen und abgelegt
$columnNum
.Die zweite besteht darin, zu entscheiden, welcher Teil des Formulars in AJAX geändert wird, und dies in einen div-Container mit der ID zu legen
columns-wrapper
.Im Rückruf müssen wir nur den Ajax-Wrapper zurückgeben.
Drupal erstellt das Formular bei jeder Ajax-Anfrage neu und fügt es in den Parameter
$form
des Rückrufs ein. Es würde keinen Sinn machen, es erneut aufzubauen.quelle
return $form['column']
, dass er null ist, da der Rückgabewert deaktiviert wirdrenderResponse()
. Könnte immer noch ein Problem mit der Parameterliste des Rückrufs sein, da wir mindestens einen Container in diesen Formularschlüssel setzen und dies diesen Fehler verhindern würde.Vermutlich fehlt Ihnen
wrapper
in Ihrem'#ajax'
(nebencallback
) die Methode , die aus dem HTML-id
Attribut des Bereichs besteht, in dem der vom Rückruf zurückgegebene Inhalt platziert werden soll. Siehe: Ajax API . Dann müssen Sie sicherstellen, dass ein solcher Containerid
existiert.Codebeispiel (vereinfacht):
Ein vollständiges Codebeispiel finden Sie unter: So fügen Sie weitere Optionen für Typradios hinzu Verwenden Sie Ajax in Drupal 8 .
quelle