Zmień istniejący formularz

12

Właśnie zaczynamy od Drupala 8 i bardzo szybko natrafiliśmy na nasz pierwszy problem.

Jak powinienem zmienić istniejący formularz w Drupal 8?

Musimy zmienić metodę zapisu formularza węzła, aby przekierować na inną stronę. Chcemy zmienić formę węzła, aby stała się czymś w rodzaju wieloetapowej. Gdy użytkownik utworzy nową treść, zostaje przekierowany do nowego formularza (utworzyliśmy), aby uzyskać więcej informacji.

Rozwiązaliśmy nasz problem z implementacją 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);
}

Następnie stworzyliśmy nową klasę formularzy, która rozszerza formę węzła i zmienia metodę zapisu.

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()]);
  }

}

Działa to doskonale, ale czy jest dobre? Jeśli inny moduł zrobi to samo, nasz kod nie będzie już wykonywany.

Jens Steppe
źródło
2
Drupal 8 nadal obsługuje hook_form_alter(). Jeśli wystarczy przekierować formularz, wystarczy dodać moduł obsługi przesyłania formularzy, który przekierowuje.
kiamlaluno
@kiamlaluno Myślę, że powinna to być odpowiedź :)
Berdir
@Berdir Samo to nie byłoby zbyt pomocne, obawiam się: moja wiedza na temat Drupala 8 jest dość ograniczona. Ponadto PO powinien wyjaśnić, co save()tak naprawdę oznacza „zmiana metody”. Czy to oznacza zmianę sposobu zapisywania danych, czy po prostu przekierowanie? W pierwszym przypadku odpowiedź jest bardziej złożona.
kiamlaluno
@kiamlaluno Thx za odpowiedź. W takim przypadku wystarczy wykonać przekierowanie po zapisaniu (), aby Twoja odpowiedź działała. Ale byłem również zainteresowany tym, jak zmienić inne rzeczy w formularzu we właściwy sposób Drupal 8. Na przykład zmień sposób zapisywania lub dodaj pola do formularza ... itd.
Jens Steppe

Odpowiedzi:

4

Wczoraj musiałem zrobić dokładnie to samo i wciąż szukam sposobu na Drupala 8, ale tego nie znalazłem. Skończyło się to tak:

<?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');
}

Nadal jestem bardzo zainteresowany zrobieniem tego inaczej, mój moduł wyglądał tak czysto bez pliku .module :).

Dagomar
źródło
3

Korzystam z Drupal 8.1.1 i próbowałem przekierować użytkowników po zmodyfikowaniu konta, tj. Kliknięciu przycisku Zapisz na stronie / user / edit. Początkowo próbowałem tego:

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

Chociaż to działało w przypadku user_login_form, nie działałoby user_form. Bo user_formmusiałem użyć

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

Mam nadzieję, że to pomoże innym, którzy natkną się na ten sam problem!

Eric C.
źródło
1

Chciałem zmienić site_information_settingsformularz, aby dodać pola.

Jako ty miałem wybór między

  • hook_form_alter(lub hook_form_FORM_ID_alter)
  • rozszerz klasę oryginalnej formy

Chciałem zrobić trochę OOP, więc zacząłem pisać usługę subskrybenta trasy zmieniającą atrybut system.site_information_settingstrasy _form.

Potem w mojej nowej klasie rozszerzającej SiteInformationForm, po dodaniu pól i ich walidatorów i rozszerzeniu funkcji wysyłania czułem się dokładnie tak samo jak ty ... A co, jeśli inny moduł przepisuje trasę formularza, aby użyć własnej klasy?

Na początku miałem wybór między dwiema opcjami ... wygląda na to, że wybrałem niewłaściwy.

hook_form_alter/ hook_form_FORM_ID_alterwydaje się być najlepszym sposobem na zmianę istniejącej formy.

MacSim
źródło
0

Wygląda na to, co chcesz zrobić, tak naprawdę nie zmienia metody zapisywania, ale zmienia przekierowanie po zapisaniu węzła.

W tej sytuacji hook_form_alterdobrym rozwiązaniem byłoby zrobienie czegoś podobnego do Drupala 7 wraz z niestandardowym modułem obsługi przesyłania (w formularzu lub przycisku, w zależności od formularza i wymagania).

To, co opisujesz w pytaniu, również działa, ale unikałbym zastąpienia klasy podstawowej, chyba że rzeczywiście chcę coś zmienić w klasie.

W każdym razie metoda zapisu została użyta jako moduł obsługi przesyłania, więc nie ma sensu zastępować, aby dodać przekierowanie.

googletorp
źródło
0

Myślę, że lepszym sposobem jest nadal użycie jednego z haczyków z rodziny form_alter, dołączenie procedury obsługi przesyłania i w ramach tego ustawienia przekierowanie.

Moim zdaniem udział w rozszerzaniu klas podstawowych w tym celu jest włochaty. Zwłaszcza, że ​​żadna funkcja się nie zmienia, tylko przekierowanie.

Kevin
źródło
0

Można utworzyć nowy EventSubscriber który nasłuchuje zdarzenia KernelEvents :: żądaniu, a następnie reagować podczas składania formularza węzła, coś jak to

W każdym razie sposób hook_form_alter działa dobrze.

ruloweb
źródło
0

To, co do tej pory znalazłem: Wdrażanie haka do zmiany formularza i próba zmiany procedur sprawdzania poprawności / przesłania w samym formularzu alter hak działa tylko, jeśli zmienisz procedury obsługi $ form ['# validate] / $ form [#submit']. (wywoływanie funkcji form_state dla tego nie będzie działać w samym haku zmiany formy)

Ale gdy wypróbujesz to w module obsługi sprawdzania poprawności, zwykle działa:

// 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);

Wynika to z tego, że forma została już całkowicie zbudowana, a nie w przypadku samej modyfikacji haka.

Pomysł jest taki: możesz dodać moduł obsługi sprawdzania poprawności jako ostatni, ocenić inne programy obsługi, które istnieją dla przesyłania, i zmienić je w tym miejscu.

Jeśli chcesz również zmienić moduły sprawdzania poprawności, upewnij się, że działa ono wcześniej, i zmień to, co chcesz w module sprawdzania poprawności.

Wciąż szukam lepszego sposobu, po prostu zawsze muszę zastąpić procedury sprawdzania poprawności / przesyłania formularza rejestracji użytkownika. Ale mogą istnieć inne moduły, które psują wdrożenie moich modułów. Więc mój moduł musiałby być w stanie to sprawdzić, i jest to możliwe w ten sposób. Zastanawiam się, czy istnieje jakaś forma encji po funkcji kompilacji, aby to ściągnąć. (coś, co działa, gdy formularz jest wypełniony i ma zostać dostarczony) (to nie jest zbyt skomplikowane w tym prostym przypadku)

Ominięcie przekierowania metody save () nie jest możliwe, ale rozbrojenie save () odbywa się w ten sposób (+ zaimplementuj własne). To prawda, że ​​klasa jest ładniejsza i oferuje łatwiejszy dostęp do obiektów / etc, ale przesłonięcie klasy podstawowej rzeczywiście prowadzi do problemów, gdy inne moduły chcą z nich korzystać. Nie jest tak w przypadku korzystania z tego kodu.

Rob C.
źródło
0

Po sprawdzeniu tego problemu znalazłem to, co powinno pasować do Twojego przypadku:

/**
 * Implements hook_entity_type_alter().
 */
function mymodule_entity_type_alter(&$entity_info) {
 $entity_info['node']->setFormClass('edit','Drupal\mymodule\Form\CustomNodeForm');
}
Ioana Todea
źródło