it-swarm.com.de

Wie mache ich eine harte Umleitung in ajaxifizierter Form?

Ich habe ein Ajax-Mehrschrittformular und möchte den Benutzer zu einer bestimmten Route umleiten, wenn bestimmte Bedingungen erfüllt sind (insbesondere, wenn der Benutzer länger als N Sekunden inaktiv ist und das Formular nach diesem Limit gesendet wird).

Ich wollte die Umleitung im Validierungshandler durchführen, hatte aber kein Glück. Also habe ich versucht Submit Handler aber immer noch kein Glück. Ich bin ziemlich durcheinander.

Ich habe versucht, die Umleitungsantwort zurückzugeben, ich habe versucht, die Umleitungsantwort für den Formularstatus festzulegen, ich habe versucht, die Umleitung für den Formularstatus festzulegen, ich habe versucht, den wiederhergestellten Formularstatus zu deaktivieren, ich habe versucht, die goto-Aktionslogik zu kopieren und den Ereignis-Dispatcher zu verwenden Ich habe versucht,\Drupal\Core\Form\FormBuilderInterface :: AJAX_FORM_REQUEST von der Anfrage zu entfernen, aber immer noch kein Glück.

Ich könnte vielleicht die Umleitung in einem Ajax-Rückruf als Umleitungsbefehl zurückgeben, aber ich möchte, dass dies mit deaktivierten js funktioniert, sodass das Aufrufen von window.location nicht ausreicht.

5
user21641

Nach ziemlich einigen Experimenten bin ich zu dieser funktionierenden Lösung gekommen.

Die Bedingung muss am Anfang des Submit-Handlers stehen:

  if ($condition) {
    $form_state->setRedirect('foo.bar')->disableRedirect(FALSE)->setRebuild(FALSE);
    // Return here so the code that activates form rebuilding for ajax or any data processing logic is not invoked.
    return;
  }

Und der Ajax-Rückruf muss folgendermaßen formatiert werden:

public static function ajaxRebuildForm(array $form, FormStateInterface $form_state) {
    /** @var \Drupal\Core\Form\FormSubmitterInterface $submitted */
    $submitter = \Drupal::service('form_submitter');
    /** @var \Symfony\Component\HttpFoundation\RedirectResponse $redirect */
    $redirect = $submitter->redirectForm($form_state);
    if ($redirect) {
      return (new AjaxResponse())->addCommand(new RedirectCommand($redirect->getTargetUrl()));
    }

    return $form;
  }

Dies funktioniert sowohl für js-fähige als auch für js-deaktivierte Umgebungen. Wenn JS aktiviert ist, erkennt der Ajax-Rückruf die eingestellte Umleitung und gibt die Ajax-Antwort mit dem Befehl redirect anstelle des Render-Arrays zurück (das auch intern in eine Ajax-Antwort umgewandelt wird). Wenn js deaktiviert ist, wird die Umleitung beim Senden des Formulars als Umleitungsantwort behandelt.


Bearbeiten: Ich habe festgestellt, dass dies keine 100% funktionierende Lösung ist. Ich habe einen Routencontroller, der entweder das Formular oder die Perofrms-Umleitung zurückgibt. Sobald ich in der ajaxifizierten Form bin und der Controller die Umleitung durchführt (dh einige Bedingungen wurden nicht erfüllt), stecke ich in der Form fest und kann nichts mehr tun, da der Ajax-Rückruf nicht ausgelöst wird, also mache ich im Grunde Anfragen an die Seite das gibt Weiterleitungen zurück und es wird keine Formularlogik mehr aufgerufen. Das heißt, ich muss wieder zusätzliche Logik in den Controller implementieren, nicht nur das Formular, da die Formular-API die Möglichkeit hat, aufgerufen zu werden und das Formular überhaupt zu verarbeiten.

Ich musste dies in meinem Controller implementieren:

  if ($request->request->get(AjaxResponseSubscriber::AJAX_REQUEST_PARAMETER)) {
    return (new AjaxResponse())
      ->addCommand(
        new RedirectCommand(
          $this->redirect(
            $this->currentRouteMatch->getRouteName()
          )->getTargetUrl()
        )
      );
  }
4
user21641

In meinem Fall (D8) musste ich nur den RedirectCommand in meinem AjaxSubmit implementieren:

Code der Senden-Schaltfläche:

$form['submit_' . $this->uniqueIdentifier] = [
  '#type' => 'submit',
  '#value' => $this->t('Submit'),
  '#attributes' => [
    'class' => ['btn', 'btn-primary']
  ],
  '#ajax' => [
    'callback' => [$this, 'submitModalFormAjax'],
    'event' => 'click',
  ],
];

Code des Rückrufs:

public function submitModalFormAjax(array $form, FormStateInterface $form_state) {
  $response = new AjaxResponse();

  if ($form_state->hasAnyErrors()) {
    // Do validation stuff here
    // ex: $response->addCommand(new ReplaceCommand... on error fields
  }

  else {
    // Do submit stuff here

    $url = Url::fromRoute('page_route');
    $command = new RedirectCommand($url->toString());
    $response->addCommand($command);
  }

  return $response;
}

Vergessen Sie nicht zu erklären:

use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\RedirectCommand;
use Drupal\Core\Url;
5
romain ni