Wywołania AJAX we wtyczce CTools Content Type?

10

Buduję typ zawartości paneli CTools (tj. Rzecz, którą wstawiasz do paneli podczas dodawania treści, a nie rodzaj węzła) i próbuję użyć #ajaxatrybutu elementu formularza, aby ustawić niektóre wartości domyślne. Zobacz kod poniżej.

Nawiasem my_module_content_type_edit_form($form, &$form_state)mówiąc, wszystko to znajduje się w wywołaniu typu zawartości .

  $form['link_type'] = array(
    '#type' => 'radios',
    '#title' => t('Link Type'),
    '#ajax' => array(
      'callback' => 'my_module_set_target'
    ),
    '#default_value' => empty($conf['link_type']) ? '_blank' : $conf['link_type'],
    '#options' => array('none'=>t('No Link'), 'internal'=>t('Internal Link'), 'external'=>t('External Link'), 'document'=>t('Document Link')),
  );

Moje oddzwonienie jest następujące.

function my_module_set_target($form, $form_state) {
  watchdog("Test", "Testing callback", array(), WATCHDOG_ALERT);
  $form['link_target']['#default_value'] = '_parent';

  return $form['link_target']['#default_value'];
}

Niezależnie od tego, czy zwrot, który sugeruję, rzeczywiście zadziała, watchdog()nawet nie zadziała.

Wiem, że CTools robi dziwne rzeczy z AJAX, ale to nie może być takie dziwne. Czy masz pomysł na to, jak bym zrobił to, co chcę?

Dzięki!

Alternatywnie: Jak ustawić wartość domyślną na podstawie wartości poprzedniej opcji formularza?

Wymyśliłem, jak to zrobić, ale jest to trochę hack - tworzysz nowe pola formularza dla każdego rozwidlenia zależności. Następnie możesz scalić wartości razem hook_content_type_edit_form_submit(), używając dowolnej, która odpowiada wartości wybranej dla komponentu, który początkowo rozwidlał wszystko.

Pozostawiam pytanie otwarte, ponieważ ja (i, szczerze mówiąc, każdy programista, z którym pracuję) naprawdę chcę dobrego sposobu na użycie AJAX w tych formularzach edycji typu zawartości Panelu.

Aktualizacja: Wygląda na to, że nie możesz robić rzeczy z #attached.

$form['link'][$i] = array(
  '#type' => 'fieldset',
  '#title' => t('Link #@num', array('@num' => $i)),
  '#collapsible' => TRUE,
  '#collapsed' => TRUE,
  '#attached' => array(
    'js' => array(
      'alert("Yay.");', 'inline'
    ),
  )
);
Aendrew
źródło
Będąc programistą Drupal typu „Panele na wszystko”, wyobrażam sobie, że mógłbym znaleźć w tym zastosowanie również w przyszłości, więc dodałem nagrodę, zobaczmy, co się stanie.
Letharion
Wow, ta nagroda przyszła i odeszła bez komentarza (Dzięki BTW, Letharion). Czy to, o co pytam, jest niemożliwe?
aendrew
Warto zauważyć, że udało mi się z powodzeniem dodać Javascript za pomocą ctools_add_js();lub drupal_add_js();na końcu hook_content_type_edit_form();. Jeśli po prostu robisz proste rzeczy związane z interfejsem użytkownika, wydaje się, że to może być najlepsze połączenie (przynajmniej dopóki ktoś nie odpowie poprawnie na to pytanie).
aendrew

Odpowiedzi:

8

Krótka odpowiedź: powinieneś użyć #ajax ['ścieżka'].

Długa odpowiedź:

Posiadanie wywołania zwrotnego ajax nie pomaga, ponieważ ctools tworzą różne formy afaik. Wywołanie zwrotne wykonane przez system / ajax nie może znaleźć pełnej definicji formularza, dlatego nie może znaleźć elementu do przetworzenia żądania ajax. Użycie #ajax [ścieżka] wyzwala po prostu element menu.

Możesz to sprawdzić samodzielnie, zrzucając formularz, używając #ajax [oddzwanianie]

function ajax_form_callback() {
  list($form, $form_state) = ajax_get_form();
  drupal_process_form($form['#form_id'], $form, $form_state);

Zmodyfikowałem simpleecontext_content_type_edit_form dodając widżet autouzupełniania użytkownika i pole, które działają :)

function simplecontext_content_type_edit_form($form, &$form_state) {
  $conf = $form_state['conf'];

  $form['owner_name'] = array(
    '#type' => 'textfield',
    '#title' => t('Username'),
    '#default_value' => 'admin',
    '#autocomplete_path' => 'user/autocomplete',
    '#size' => '6',
    '#maxlength' => '60',
    '#description' => '$description',
  );

  $form['link_type'] = array(
    '#type' => 'radios',
    '#title' => t('Link Type'),
    '#ajax' => array(
      'path' => 'my_module_set_target'
    ),
    '#default_value' => empty($conf['link_type']) ? '_blank' : $conf['link_type'],
    '#options' => array('none' => t('No Link'), 'internal' => t('Internal Link'), 'external' => t('External Link'), 'document' => t('Document Link')),
  );
...

Kiedy teraz używasz ścieżki #ajax, musisz dodać element menu, tak jak mi się podobało

<?php

function my_module_menu() {
  $items = array(
    'my_module_set_target' => array(
      'title' => 'AJAX Example',
      'page callback' => 'my_module_set_target',
      'access callback' => TRUE,
      'expanded' => TRUE,
    )
  );
  return $items;
}

function my_module_set_target() {
  drupal_json_output( array('data' => "ABC"));
}

Nitpick o #attached [js]: wstawiany js powinien mieć wartość key =>, taką jak:

'#attached' => array(
  'js' => array(
    'alert("Yay.");' => 'inline',
  ),
),

Użyłem Firebuga, aby sprawdzić wynikową wartość, a nie wynikowy efekt. Mam więc nadzieję, że to pomoże rozwiązać problem.

Clemens Tolboom
źródło
Łał. Jestem tak podekscytowany, że w końcu mam odpowiedź na to pytanie. Spróbuję za chwilę. Dziękuję również za notatkę na # attached bit, to właściwie to, co początkowo miałem (ale zmieniłem to, ponieważ uznałem, że to nie może mieć racji).
aendrew
A więc sukces? Byłoby ciekawie wiedzieć, zanim skończy się nagroda :)
Letharion
Mam nadzieję, że dostanę nagrodę: p
Clemens Tolboom,
Przepraszam za opóźnienie z tym, że mam trochę czasu na uruchomienie - kiedy próbuję zwrócić tablicę $ form, mówi mi, że moja funkcja sprawdzania poprawności nie jest zdefiniowana. Tak jest, a kiedy próbuję ponownie zadeklarować go w moim module (w przeciwieństwie do pliku wtyczki typu zawartości), mówi mi, że ponownie go deklaruję. Zgaduję, że to nie jest to, co muszę zrobić, ale nie mogę wymyślić, jak ustrukturyzować drupal_json_output, więc wyświetla coś, co moja postać zinterpretuje jako znaczącą odpowiedź. Jakaś pomoc? Lepszy przykład oddzwonienia pomógłby LOTowi. Dzięki!
aendrew
Brakowało mi małej części twojego pytania, która dotyczy wartości zwracanej : return $ form ['link_target'] ['# default_value']; który próbuje przywrócić formularz drupal do kontekstu HTML / javascript . To nie zadziała. Czy widziałeś podobne rzeczy, które chcesz w interfejsie użytkownika paneli? (Sam czasami wyłączam JavaScript z interfejsem użytkownika widoków, aby zobaczyć przepływ pracy non js) (edytowałem ten komentarz zillion razy ... niezręcznie)
Clemens Tolboom 10.10
2

Miałem podobny problem, gdy chciałem dołączyć typ elementu Media do wtyczki typu zawartości CTools, która również używa ajax do wybierania obrazu.

Używa własnego ustawienia „ścieżki” ajax, zamiast ustawienia „wywołania zwrotnego”, ale podczas wybierania obrazu formularz został przebudowany bez elementu media w całości.

Śledziłem to do faktu, że drupal_rebuild_form nie mógł znaleźć ani funkcji otoki formularza CTools, ani funkcji formularza ustawień rzeczywistych. Naprawiłem to, dodając następujące wiersze kodu do formularza ustawień narzędzi:

function custom_module_my_content_plugin_content_type_edit_form($form, &$form_state) {

$background_image = isset($conf['background_image']) ? $conf['background_image'] : array();
  $form['background_image'] = array(
    '#title' => t('Background image'),
    '#default_value' => $background_image,
    '#type' => 'media',
    '#input' => TRUE,
    '#extended' => TRUE,
    '#tree' => TRUE,
    '#media_options' => array(),
  );

  // The two function calls below are necessary if we want to use a media
  // element type, because it causes ajax requests, which in turn call
  // drupal_form_rebuild(), and without the below includes, Drupal will
  // not be able to rebuild the form.

  // Include the CTools content type plugin file, because it provides
  // the ctools_content_configure_form_defaults() function, which is needed
  // when rebuilding the form, because of an ajax action, like selecting
  // a media element.
  ctools_form_include($form_state, 'content');

  // Include this plugin file as well, so that when the form is rebuilt, it
  // can successfully retrieve the settings form.
  ctools_form_include($form_state, 'my_content_plugin', 'custom_module', 'plugins/content_types/my_content_plugin');

}

Być może brakuje mi czegoś oczywistego, dlaczego pliki dołączeń nie są ładowane, ale włączenie ich ręcznie rozwiązało problem.

Placinta
źródło
0

ze swojej strony musiałem napisać funkcję opakowania formularza w pliku .module i ręcznie dołączyć okienko (w którym zdefiniowano oryginalną treść formularza) w następujący sposób:

function mymodule_form($form, &$form_state) {
  // include mymodule/panes/mypane.inc
  ctools_include('mypane', 'mymodule', 'panes');
  return mymodule_form_content($form, $form_state);
}

Teraz, podczas wywoływania ajax, Drupal jest w stanie pobrać mój formularz, dzięki czemu mogę użyć standardowego interfejsu API formularza AJAX.

Pierco
źródło