Ändern Sie ein vorhandenes Formular


12

Wir haben gerade mit Drupal 8 angefangen und sind sehr schnell auf unser erstes Problem gestoßen.

Wie soll ich ein bestehendes Formular in Drupal 8 ändern?

Wir müssen die Speichermethode für das Knotenformular ändern, um auf eine andere Seite umzuleiten. Wir möchten die Knotenform so ändern, dass sie einer mehrstufigen Form ähnelt. Nachdem der Benutzer neuen Inhalt erstellt hat, wird er in ein neues Formular umgeleitet (das wir erstellt haben), um weitere Informationen zu erhalten.

Wir haben unser Problem gelöst hook_entity_type_alter().

function mymodule_entity_type_alter(&$entity_info) {
  $handlers = $entity_info['node']->get('handlers');
  $handlers['form']['default'] =    'Drupal\mymodule\Form\MyExtendedNodeForm';
  $handlers['form']['edit'] = 'Drupal\mymodule\Form\MyExtendedNodeForm';
  $entity_info['node']->set('handlers', $handlers);
}

Anschließend haben wir eine neue Formularklasse erstellt, die das Knotenformular erweitert und die Speichermethode ändert.

class MyExtendedNodeForm extends NodeForm {

    public function save(array $form, FormStateInterface $form_state) {
      parent::save($form, $form_state);
      $node = $this->entity;
      $form_state->setRedirect('entity.regions.add_form', ['nid' => $node->id()]);
  }

}

Das funktioniert einwandfrei, aber ist es gut? Wenn ein anderes Modul dasselbe tut, wird unser Code nicht mehr ausgeführt.


2
Drupal 8 unterstützt weiterhin hook_form_alter(). Wenn Sie das Formular nur umleiten müssen, ist es ausreichend, einen Formularübergabehandler hinzuzufügen, der die Umleitung ausführt.
kiamlaluno

@ Kiamlaluno Das sollte die Antwort sein, denke ich :)
Berdir

@Berdir Das alleine wäre leider nicht sehr hilfreich: Meine Kenntnisse über Drupal 8 sind ziemlich begrenzt. Außerdem sollte das OP klarstellen, was "Änderung der save()Methode" tatsächlich bedeutet. Bedeutet das, die Art und Weise zu ändern, wie Daten gespeichert werden, oder einfach eine Umleitung durchzuführen? Im ersten Fall ist die Antwort komplexer.
kiamlaluno

@ kiamlaluno Thx für die Antwort. In diesem Fall müssen wir erst nach save () eine Umleitung durchführen, damit Ihre Antwort funktioniert. Aber ich war auch daran interessiert, wie ich andere Dinge in der Form auf die richtige Art und Weise in Drupal 8 ändern kann. Ändern Sie beispielsweise, wie es gespeichert wird, oder fügen Sie dem Formular Felder hinzu. Usw.
Jens Steppe

Antworten:


4

Ich musste gestern genau das Gleiche tun, und ich suche noch nach einem weiteren Drupal 8-Verfahren, habe es aber nicht gefunden. Am Ende habe ich es so gemacht:

<?php

/**
 * @file
 * This is my module.
 */

use Drupal\Core\Form\FormStateInterface;
use Symfony\Component\HttpFoundation\Request;

/**
 * Implements hook_form_alter().
 */
function MODULE_form_alter(array &$form, FormStateInterface $form_state, $form_id) {
  if ($form_id == 'user_form') {
    $form['actions']['submit']['#submit'][] = '_MODULE_goto';
  }
}

/**
 * Make the form go to route.id.
 */
function _MODULE_goto($form, FormStateInterface $form_state) {
  $form_state->setRedirect('route.id');
}

Ich bin immer noch sehr daran interessiert, es anders zu machen, mein Modul sah ohne die .module-Datei so sauber aus :).


3

Ich verwende Drupal 8.1.1 und habe versucht, Benutzer umzuleiten, nachdem sie ihr Konto geändert haben, dh auf der Seite / user / edit auf die Schaltfläche Save (Speichern) geklickt. Ich habe es anfangs versucht:

/**
 * Implements hook_form_alter().
*/
function MODULE_form_alter(array &$form, FormStateInterface $form_state, $form_id) {
  if ($form_id == 'user_form') {
    $form['#submit'][] = '_MODULE_goto';
  }
}

Während das für die funktionierte user_login_form, würde es nicht für die funktionieren user_form. Denn user_formich musste verwenden

$form['actions']['submit']['#submit'][] = '_MODULE_goto';

Ich hoffe das hilft anderen, die über das gleiche Problem stolpern!


1

Nun, ich wollte das site_information_settingsFormular ändern , um einige Felder hinzuzufügen.

Als Sie hatte ich die Wahl zwischen

  • hook_form_alter(oder hook_form_FORM_ID_alter)
  • Erweitern Sie die ursprüngliche Formularklasse

Wollte etwas OOP machen, also fing ich an, einen Routenteilnehmerdienst zu schreiben, der system.site_information_settingsdas _formAttribut der Route ändert .

Dann habe ich in meiner neuen Klasse die Erweiterung SiteInformationForm, nachdem die Felder und deren Validatoren hinzugefügt und die Submit-Funktion erweitert wurden, genauso empfunden wie Sie ... Was nun, wenn ein anderes Modul auch die Route des Formulars umschreibt, um seine eigene Klasse zu verwenden?

Zurück zum Anfang hatte ich die Wahl zwischen zwei Optionen ... es scheint, als hätte ich die falsche ausgewählt.

hook_form_alterIch hook_form_FORM_ID_alterscheine der beste Weg zu sein, ein bestehendes Formular zu ändern.


0

Es sieht aus wie das, was Sie tun möchten, es ist nicht wirklich, die Speichermethode zu ändern, sondern die Umleitung zu ändern, wenn ein Knoten gespeichert wird.

In dieser Situation ist hook_form_alteres eine gute Lösung , ähnlich wie bei Drupal 7 einen benutzerdefinierten Submit-Handler (auf dem Formular oder der Schaltfläche, je nach Formular und Anforderung) zu verwenden.

Was Sie in der Frage beschreiben, funktioniert auch, aber ich würde es vermeiden, die Basisklasse zu überschreiben, es sei denn, ich möchte tatsächlich etwas in der Klasse ändern.

Die Speichermethode wird sowieso nur als Submit-Handler verwendet. Es macht also wenig Sinn, sie nur zu überschreiben, um eine Umleitung hinzuzufügen.


0

Ich denke, die bessere Methode ist es, immer noch einen der Hooks aus der form_alter-Familie zu verwenden, einen Submit-Handler anzuhängen und in diesem die Umleitung festzulegen.

Die Erweiterung der Basisklassen dazu beizutragen, ist meiner Meinung nach haarig. Zumal sich keine Funktion ändert, sondern nur umleitet.


0

Sie können einen neuen EventSubscriber erstellen, der das Ereignis KernelEvents :: REQUEST abhört, und dann reagieren, wenn Sie ein Knotenformular wie dieses senden

Wie auch immer, der hook_form_alter Weg funktioniert in Ordnung.


0

Was ich bisher gefunden habe: Einen Formularänderungs-Hook implementieren und versuchen, die Validate / Submit-Handler im Formularänderungs-Hook selbst zu ändern, funktioniert nur, wenn Sie die Handler $ form ['# validate] / $ form [#submit'] ändern. (Das Aufrufen von form_state-Funktionen funktioniert nicht im form alter hook selbst.)

Wenn Sie dies jedoch in einem Validierungs-Handler versuchen, funktioniert Folgendes:

// Load form submit handlers.
$submit_handlers = $form_state->getSubmitHandlers();

// Drop the core entity submitForm function.
$key_core_submit = array_search('::submitForm', $submit_handlers);
if ($key_core_submit !== FALSE) {
  unset($submit_handlers[$key_core_submit]);
  // Add your own submit handler.
  array_unshift($submit_handlers, 'yourmodule_submit_handler');
}
// Update submit handlers.
$form_state->setSubmitHandlers($submit_handlers);

Dies liegt daran, dass das Formular jetzt vollständig erstellt wurde und nicht mehr im Formularänderungs-Hook selbst.

Die Idee ist: Sie können einen Validierungs-Handler als letzten hinzufügen, andere Handler, die für die Übermittlung vorhanden sind, auswerten und direkt dort ändern.

Wenn Sie auch Validierungshandler ändern möchten, stellen Sie sicher, dass Ihre vor allen anderen ausgeführt werden, und ändern Sie, was Sie im Validierungshandler möchten.

Ich bin immer auf der Suche nach einem besseren Weg, aber ich muss immer nur die Validate / Submit-Handler für das Benutzerregistrierungsformular ersetzen. Es können jedoch auch andere Module vorhanden sein, die die Implementierung meiner Module beeinträchtigen. Also müsste mein Modul in der Lage sein, dies zu überprüfen, und das ist auf diese Weise möglich. Ich frage mich, ob es eine Entity-Form nach der Build-Funktion gibt, die dies ermöglicht. (etwas, das ausgeführt wird, wenn das Formular ausgefüllt wurde und zugestellt werden soll) (für diesen einfachen Fall ist das nicht allzu komplex)

Das Umgehen der Weiterleitung der save () -Methode ist nicht möglich, aber das Deaktivieren der save () -Methode erfolgt auf diese Weise (+ Implementieren Ihrer eigenen). Eine Klasse ist zwar besser und bietet einen einfacheren Zugriff auf Objekte / etc, aber das Überschreiben einer Kernklasse führt in der Tat zu Problemen, wenn andere Module diese verwenden möchten. Das ist nicht der Fall, wenn Sie diesen Code verwenden.


0

Nachdem ich dieses Problem überprüft habe, habe ich Folgendes gefunden, das zu Ihrem Fall passen sollte:

/**
 * Implements hook_entity_type_alter().
 */
function mymodule_entity_type_alter(&$entity_info) {
 $entity_info['node']->setFormClass('edit','Drupal\mymodule\Form\CustomNodeForm');
}
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.