AJAX вызывает в плагине типа контента CTools?

10

Я создаю тип содержимого панелей CTools (то есть то, что вы вставляете в панели при добавлении контента, а не тип узла), и я пытаюсь использовать #ajaxатрибут элемента формы, чтобы установить некоторые значения по умолчанию. Смотрите код ниже.

my_module_content_type_edit_form($form, &$form_state)Кстати, это все внутри вызова типа контента .

  $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')),
  );

Мой обратный звонок следующий.

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'];
}

Независимо от того, будет ли возвращение, которое я предлагаю, действительно работать, watchdog()даже не работает.

Я знаю, что CTools делает странные вещи с AJAX, но это не может быть так странно. У вас есть идеи о том, как я буду делать то, что хочу?

Спасибо!

Альтернативный вариант: как установить значение по умолчанию на основе значения предыдущего параметра формы?

Я понял, как это сделать, но это немного глупо - вы создаете новые поля формы для каждого форка зависимости. Затем вы можете объединить значения вместе hook_content_type_edit_form_submit(), используя то, что соответствует значению, выбранному для компонента, который изначально разветвлялся.

Я оставляю вопрос открытым, потому что я (и, честно говоря, каждый программист, с которым я работаю) действительно хочу хороший способ использовать AJAX в этих формах редактирования типов контента Panel.

Обновление: Похоже, что вы не можете делать вещи с #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
источник
Будучи разработчиком Drupal типа «Панели для всего», я полагаю, что смогу найти это и в будущем, поэтому я добавил награду, посмотрим, что произойдет.
Летарион
Вау, эта награда пришла и ушла без комментариев (спасибо, кстати, Летарион). То, что я спрашиваю, невозможно или что-то еще?
aendrew
Стоит отметить, что я смог успешно добавить Javascript, используя ctools_add_js();или drupal_add_js();в конце hook_content_type_edit_form();. Если вы просто делаете простые вещи, связанные с пользовательским интерфейсом, кажется, что это может быть лучшим вызовом (по крайней мере, пока кто-то правильно не ответит на этот вопрос).
aendrew

Ответы:

8

Краткий ответ: вы должны использовать #ajax ['path'].

Длинный ответ:

Наличие обратного вызова ajax не помогает, поскольку ctools создает свои формы по-разному. Обратный вызов, выполняемый system / ajax, не может найти полное определение формы, поэтому не может найти элемент, для которого обрабатывается запрос ajax. Использование #ajax [путь] просто вызывает пункт меню.

Вы можете проверить сами, выгрузив форму при использовании #ajax [callback]

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

Я изменил simplecontext_content_type_edit_form, добавив виджет автозаполнения пользователя и ваше поле, которые оба работают :)

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')),
  );
...

Так как вы сейчас используете путь #ajax, вам нужно добавить пункт меню, как я хотел

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

Нечетная пометка о #attached [js]: встроенный js должен иметь значение key =>, например:

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

Я использовал Firebug для проверки результирующего значения, а не результата. Поэтому я надеюсь, что это поможет решить вашу проблему.

Клеменс Толбом
источник
Ух ты. Я так рад, что наконец-то получил ответ на этот вопрос. Попробую это немного. Спасибо также за примечание о #attached бите, это на самом деле то, что у меня было изначально (но изменил его, потому что я подумал, что это не может быть правильно).
'32
Итак, какой успех? Было бы интересно узнать, когда
награда
Я надеюсь, что получу свою награду: p
Clemens Tolboom
Извините за задержку с этим, имея некоторое время, чтобы это заработало - когда я пытаюсь вернуть массив $ form, он говорит мне, что моя функция проверки не определена. Это так, и когда я пытаюсь повторно объявить его в моем модуле (в отличие от файла плагина типа контента), он говорит мне, что я его заново делаю. Я предполагаю, что это не то, что мне нужно сделать, но я не могу понять, как структурировать drupal_json_output, чтобы он выводил что-то, что моя форма будет интерпретировать как значимый ответ. Любая помощь? Лучший пример обратного вызова поможет много. Спасибо!
aendrew
Я пропустил крошечную часть вашего вопроса, касающуюся возвращаемого значения: return $ form ['link_target'] ['# default_value']; что вы пытаетесь вернуть друпал форму в контекст html / javascript . Это не будет работать. Вы видели похожую вещь, что вы хотите в панели интерфейса? (Я сам отключаю JavaScript время от времени с помощью пользовательского интерфейса представлений, чтобы увидеть рабочий процесс, не относящийся к js) (редактировал этот комментарий миллионы раз ... неловко)
Клеменс Толбоом,
2

У меня была похожая проблема, когда я хотел включить тип элемента Media в плагин типа контента CTools, который также использует ajax для выбора изображения.

Он использует собственный параметр пути 'ajax' вместо параметра 'обратный вызов', но при выборе изображения форма была перестроена без использования медиа-элемента полностью.

Я проследил это до того, что drupal_rebuild_form не смог найти ни функцию-оболочку формы CTools, ни функцию формы реальных настроек. Поэтому я исправил это, добавив следующие строки кода в форму настроек ctools:

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

}

Может быть, я упускаю что-то очевидное, почему включаемые файлы не загружаются, но включение их вручную решило проблему для меня.

Плэчинтэ
источник
0

со своей стороны я должен был написать функцию обертки формы в файле .module и вручную включить панель (где определено исходное содержимое формы), например:

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

Теперь, во время вызова ajax, Drupal может получить мою форму, чтобы я мог использовать стандартный API формы AJAX.

Pierco
источник