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(),使用与最初为所有分叉的组件选择的值相对应的任何一个。

我将问题悬而未决,因为我(坦率地说,与我合作的每个程序员)都确实希望有一种好的方法来在这些Panel内容类型编辑表单中使用AJAX。

更新:看来#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'
    ),
  )
);

作为一名Drupal开发人员的“万能面板”类型,我想我将来也可以找到这种用途,所以我添加了一笔赏金,让我们看看会发生什么。
Letharion

哇,那笔赏金来了也没来得及评论(感谢BTW,Letharion)。我要的是不可能的吗?
2012年

值得注意的是,我已经能够使用ctools_add_js();drupal_add_js();末尾成功添加Javascript hook_content_type_edit_form();。如果您只是在做简单的与UI相关的事情,那似乎是最好的选择(至少在有人正确回答此问题之前)。
aendrew's

Answers:


8

简短的答案:您应该使用#ajax ['path']。

长答案:

进行ajax回调无济于事,因为ctools会创建不同形式的afaik。系统/ ajax完成的回调无法找到完整的表单定义,因此无法找到要处理其ajax请求的元素。使用#ajax [path]只会触发一个菜单项。

您可以在使用#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 => value,例如:

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

我使用Firebug来检查结果值而不是结果。因此,我希望这有助于解决您的问题。


哇。我很高兴最终对这个问题有一个答案。会尝试一下。也要感谢#attached位上的注释,这实际上是我最初拥有的(但是更改了它,因为我认为那是不对的)。
2012年

那么,成功了吗?在赏金结束之前知道会很有趣:)
Letharion 2012年

我希望我能得到赏金:p
Clemens Tolboom 2012年

很抱歉延迟了,花了一点时间使它起作用-当我尝试返回$ form数组时,它告诉我我的validate函数未定义。是的,当我尝试在模块中重新声明它(与内容类型插件文件相对)时,它告诉我正在重新声明它。我猜这不是我需要做的,但是我无法弄清楚如何构造drupal_json_output,因此它输出的内容将被我的表单解释为有意义的响应。有什么帮助吗?一个更好的示例回调将帮助很多。谢谢!
2012年

我错过了您的问题中的一小部分,即返回值:return $ form ['link_target'] ['#default_value']; 这是您尝试将drupal表单返回到html / javascript上下文。这是行不通的。您是否在面板UI中看到了想要的类似内容?(我自己不时禁用JavaScript,然后使用视图UI只是为了查看非js工作流)(对此评论进行了无数次的编辑……很尴尬)
Clemens Tolboom 2012年

2

我遇到了类似的问题,我想在CTools内容类型插件中包含Media元素类型,该插件也使用ajax选择图像。

它使用自己的ajax“路径”设置,而不是“回调”设置,但是当选择图像时,将完全不使用media元素来重建表单。

我将其追溯到以下事实: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能够检索我的表单,因此我可以使用标准的AJAX表单API。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.