Czy możliwe jest samodzielne wyświetlenie działającego formularza pola widżetu?

21

Jestem zainteresowany osadzeniem formularza widżetu pola poza kontekstem formularza edycji całego węzła.

W przeszłości wyświetlałem pełne formularze za pomocą drupal_get_form, ale wydaje się, że nie dotyczy to pojedynczych formularzy pól.

Czy możliwe jest wyświetlenie działającego formularza Field Widget? Jaki byłby to najlepszy sposób?

Zarówno widżety pola, jak i „normalne” formularze wydają się bardzo do siebie podobne, więc jeśli nie jest to możliwe, co byłoby wymagane do „zmiany” formularza widżetu na normalny?

To pytanie pojawia się pytać o coś podobnego, ale nie rozumiem odpowiedzi. Ta odpowiedź określa użycie hook_field_widget_form_alter ; nie rozumiem, jak wyświetlić formularz pola, a nie jak go zaczepić po utworzeniu.

SMTF
źródło

Odpowiedzi:

18

VBO robi coś takiego w pliku edit.action.inc:

$form_key = 'bundle_' . $bundle_name;
$form[$form_key] = array(
  '#type' => 'fieldset',
  '#title' => $label,
  '#parents' => array($form_key),
);  
field_attach_form($context['entity_type'], $entity, $form[$form_key], $form_state, LANGUAGE_NONE);  

Potrzebujesz więc typu encji, encji (która może być pustym obiektem tylko z zestawem kluczy pakietu, tego właśnie się używa), formy dodawania widżetów i języka. Jeśli chcesz osadzić widżety głębiej w formularzu (nie w $ form, ale w $ form [$ form_key] tak jak ja, lub jeszcze głębiej), to tablica formularzy musi mieć ustawione #parents.

Oczywiście zauważ, że spowoduje to osadzenie widżetów wszystkich pól należących do tego typu encji i pakietu. Tak zostały napisane funkcje dołączania. Poruszanie się po nim wymagałoby ponownego opracowania całkiem dużej ilości kodu; zobacz faktyczny kod, który wykonuje podnoszenie ciężarów. To, co robię, to przeglądanie instancji pól, uzyskiwanie każdego $ nazwa_pola, a jeśli ten typ pola mnie nie interesuje, ustawiam, $form[$form_key][$field_name]['#access'] = FALSE; który ukrywa te widżety.

EDYCJA: Okay, ctools ma ctools_field_invoke_field (), co teoretycznie może pozwolić ci na pracę dla poszczególnych pól. Jednak nigdy tego nie użyłem. Powyższy tekst to moje bezpośrednie doświadczenie.

Bojan Zivanovic
źródło
Świetna odpowiedź. Spędziłem z tym większą część dnia i działało tak, jak chciałem. Nagroda przyznana i polecam PO zaakceptować to jako poprawną odpowiedź. Skończyło się na tym, że stworzyłem fikcyjny typ zawartości, aby móc kontrolować moje pola jak każdy inny typ zawartości, zamiast ustawiania, #access = FALSEktóre w tym kontekście wydawały się hakerskie.
Letharion
Dziękujemy za potwierdzenie tego, czego się obawiałem: że widget z pojedynczym polem nie jest praktycznie sam w sobie użyteczny.
SMTF,
7

Intensywnie korzystałem z funkcji sugerowanej przez ttk, ale myślę, że ostatnia aktualizacja pomieszała ...

Oto nowa wersja poprzedniego rozwiązania, która działa dobrze z Drupal 7.22 i ctools 7.x-1.3.

Tak jak w poprzednim poście, wywołujesz swoją funkcję niestandardową w następujący sposób:

my_field_attach_form('field_body', 'node', 'blog',  $node, $form, $form_state, LANGUAGE_NONE);

Zauważ, że pakiet encji jest teraz parametrem. Zrobiłem to, ponieważ użyłem tej funkcji również do edycji użytkowników. W ten sposób można go również wykorzystać do określenia taksonomii lub dowolnego innego podmiotu.

I my_field_attach_formjest zdefiniowany jako:

function my_field_attach_form($field_name, $entity_type, $bundle, $entity, &$form, &$form_state, $langcode = NULL) {

  // Set #parents to 'top-level' if it doesn't exist.
  $form += array('#parents' => array());

  // If no language is provided use the default site language.
  $options = array(
    'language' => field_valid_language($langcode),
    'default' => TRUE,
  );

  // Append to the form
  ctools_include('fields');
  $field_instance = field_info_instance($entity_type, $field_name, $bundle);
  $form += (array) ctools_field_invoke_field($field_instance, 'form', $entity_type, $entity, $form, $form_state, $options);
}

Ta funkcja pozwoliła mi zaoszczędzić dużo czasu. Mam nadzieję, że również dla Ciebie!

jmcouillard
źródło
5

Oto rozwiązanie wykorzystujące tę ctools_field_invoke_field()metodę. W funkcji formularza niestandardowego dodaj:

$form = array();
$node = new stdClass();
$node->type = 'blog';
my_field_attach_form('field_body', 'node', $node, $form, $form_state, LANGUAGE_NONE);

gdzie my_field_attach_formfunkcja jest zdefiniowana jako

function my_field_attach_form($field_name, $entity_type, $entity, &$form, &$form_state, $langcode = NULL) {
  // Set #parents to 'top-level' if it doesn't exist.
  $form += array('#parents' => array());

  // If no language is provided use the default site language.
  $options = array(
    'language' => field_valid_language($langcode),
    'default' => TRUE,
  );
  module_load_include("inc","ctools","includes/fields");
  $form += (array) ctools_field_invoke_field($field_name, 'form', $entity_type, $entity, $form, $form_state, $options);
}

Pamiętaj, że Twoja witryna musi mieć włączone narzędzia Ctools. Szkoda, że ​​Drupal nie zawiera domyślnie takiej funkcji pomocnika.

ttk
źródło
2

Nie mogłem uruchomić metody ctools i postanowiłem zrobić to w ten sposób.

Ten kod byłby wewnątrz funkcji formularza, więc $ form i $ form_state zostałyby już przekazane.

function form_function($form, &$form_state) {

Najpierw utwórz pusty węzeł typu, który ma pole, które chcesz renderować.

    $entity = new stdClass();
    $entity->title = "Temp Object";
    $entity->type = "node_type";
    node_object_prepare($entity);

Zduplikowałem zmienne formularza, aby nie zablokować oryginału.

    $temp_form       = $form;
    $temp_form_state = $form_state;
    field_attach_form("node", $entity, $temp_form, $temp_form_state);

Wyciągnij pole, którego szukasz, i dodaj je do formularza.

    $form["field"] = $temp_form["existing_field"];
}

Użyłem tej metody do renderowania widżetu wyboru taksonomii, widżetu pól wyboru taksonomii i widżetu Hierarchical Select w formularzu niestandardowym. (Widżet autouzupełniania systematyki renderuje, ale zgłasza błąd przy wysyłaniu)

Na koniec renderuj i drukuj

drupal_render(drupal_get_form("form_function"))
Scott Joudry
źródło
To wydaje się być łatwym sposobem na użycie widgetu pola w niestandardowej formie. Zależy to jednak od istniejącego pakietu. W moim przypadku używam fikcyjnego typu zawartości, w którym w razie potrzeby tworzę i konfiguruję pola. Jest to nieco zuchwałe, ale konieczne również w przypadku innych metod. Uwaga: ctools_field_invoke_field()wyżej opisana metoda również działa.
Bernhard Fürst,
0

Za pomocą stworzyłem formularze z pól niepodzielnych

field_default_form('entity_type', $entity, $field,$field_instance,LANGUAGE_NONE,$default_value, $form, $form_state);

powinno to zwrócić wymagany formularz widżetu, którego można użyć w dowolnej formie

 $custom_form['form_element_to_display'] = field_default_form('entity_type', $entity, $field,$field_instance,LANGUAGE_NONE,$default_value, $custom_form, $custom_form_state);

Aby uzyskać wartości powyższego parametru 2, użyj:

$field = field_info_field($field_name);
$field_instance = field_info_instance('node', $field_name, $node_type);

W przypadku innych parametrów możesz sprawdzić link interfejsu API tutaj

Zwraca domyślny formularz widgetu zdefiniowany w polu typów zawartości.

Mam nadzieję, że to komuś pomoże :)

akshay daxini
źródło