通过ajax更新选择列表值时如何避免“检测到非法选择”?


10

我有四个实体引用字段,用于表单中的用户实体。主机表单是节点编辑表单。其中三个是选择列表,最后一个是内联实体表单

通过IEF添加用户实体后,我尝试更新选择列表值:

function ebep_users_feature_users_list_ajax($form, $form_state) {

  $ief = array_shift($form_state['inline_entity_form']);
  $options = array('_node' => t('- None -'));
  $commands = array();

  foreach($ief['entities'] as $data) {
    $options[$data['entity']->uid] = $data['entity']->name;
  }

  foreach(_ebep_users_feature_getUserListFieldNames() as $fieldName) {
    $form[$fieldName]['und']['#options'] = $options;
    $commands[] = ajax_command_replace('#'.$fieldName.'_wrapper', drupal_render($form[$fieldName]));
  }

  return array('#type' => 'ajax', '#commands' => $commands);
}

它可以工作,但是当我尝试通过IEF添加另一个用户时,我得到了:

检测到非法选择。请联系网站管理员。


Related右边列出的此处有任何问题解决了吗?
Jimajamma 2013年

@Jimajamma似乎在ajax回调形式上无法正常工作。如何启用它?$ form_state ['rebuild'] = TRUE什么都不做...
Codium

@Jimajamma,因此相关解决方案不起作用
Codium

我已经在这里回答了您的问题,因为它是一个重复的问题drupal.stackexchange.com/questions/15989/…–
新浪Salek

Answers:


15

---原始答案。错误,请检查下面的更新。

刚设定

$bla['#validated'] = TRUE

在选择中,将使用AJAX更新。

结帐“已检测到非法选择”

-更新2019年12月17日-

实际上,这不是一个好建议,那是很久以前的事,现在我知道了。

Ajax回调函数应该只返回已更改的表单或一些ajax命令。

在这种情况下,必须对表单功能或表单变更挂钩进行表单修改。每次调用ajax回调时,都会运行表单构建和验证功能。只需在表单构建或更改函数上检查$ form_state并相应地调整值即可。

请参阅解决错误“检测到非法选择...”。


1
如果我没记错的话,我尝试过此方法,但没有成功,谢谢
Codium 2014年

1
恐怕这对我也不起作用。
kevin.coyle,2015年

这是否会使表格的安全性降低?
宾尼(Binny),

是的,以前的所有评论都是正确的。答案已更新。
jaimealsilva

3

我在Drupal 6中已经多次遇到此问题,通过Ajax更改“选择”列表的值。

您可以做的是

  1. 如果可能,请尝试在Field API中插入所有可能的值,您需要编辑该字段,然后在更改值时,必须确保列表中仅列出了值。
  2. 我实现的解决方案是,您可以将字段类型从“选择列表”更改为文本字段,也可以从“字段API”更改为该字段类型,并要求Drupal按原样保存该值。现在,在表单运行时,您将必须更改表单,更改类型以选择列表,并按需输入选项。同样在提交时,您将必须指定字段所需的正确值,该值将按原样保存在DB中。确保在默认表单提交处理程序之前调用了您的提交处理程序,因为您可以使用array_merge

如果第一个解决方案适合您,您将节省大量时间进行编码和测试。但是,如果下拉列表中的列表是动态的,并且您无法控制它,则可能必须采用第二种解决方案。

如果您遇到任何问题,请发帖,对于我的项目,我已经在此问题上做了很多工作,并且我做了大约50个表格,PHEW!:)


3

我发现最好的方法是#value在选择列表上进行设置。

如果我们在formstate中有该值,并且该值在我们的选项中,则不会收到错误。如果选项中没有我们的值,请选择选项中的第一个选项并使用它。

$form['example'] = array(
    '#type' => 'select',
    '#title' => t('Example'),
    '#options' => $options,
    '#value' => isset($form_state['values']['example']) && in_array($form_state['values']['example'],$options)?$form_state['values']['example']:key($options),
  );

2

我的解决方案:

/**
 * Implements hook_form_FORM_ID_alter()
 */
function ebep_users_feature_form_ebep_exhibitor_profile_node_form_alter(&$form, &$form_state, $form_id) {

  foreach(_ebep_users_feature_getUserListFieldNames() as $fieldName) {
    $form[$fieldName]['und']['#prefix'] = '<div id="'.$fieldName . '_wrapper">';
    $form[$fieldName]['und']['#suffix'] = '</div>';
    $form[$fieldName]['und']['#options'] = _ebep_users_feature_getOptionsValuesFromIEFList($form_state);
  }

  $form['#attached']['css'] = array(
    drupal_get_path('module', 'ebep_users_feature') . '/assets/styles.css',
  );

  $form['#attached']['js'] = array(
    drupal_get_path('module', 'ebep_users_feature') . '/assets/scripts.js',
  );

  $form['users_refresh'] = array(
    '#type' => 'submit',
    '#value' => t('Refresh users list'),
    '#ajax' => array(
      'callback' => 'ebep_users_feature_users_list_ajax',
    ),
  );
}

function ebep_users_feature_users_list_ajax($form, $form_state) {

  $commands = array();

  foreach(_ebep_users_feature_getUserListFieldNames() as $fieldName) {
    $form[$fieldName]['und']['#options'] = _ebep_users_feature_getOptionsValuesFromIEFList($form_state);
    $commands[] = ajax_command_replace('#'.$fieldName.'_wrapper', drupal_render($form[$fieldName]));
  }

  return array('#type' => 'ajax', '#commands' => $commands);
}

function _ebep_users_feature_getOptionsValuesFromIEFList($form_state) {
  static $options = array();

  if (empty($options)) {
    $ief = array_shift($form_state['inline_entity_form']);
    $options['_node'] = t('- None -');

    foreach($ief['entities'] as $data) {
      $options[$data['entity']->uid] = $data['entity']->name;
    }
  }

  return $options;
}

-1

在您的ajax回调中,添加:

...

drupal_get_messages();
form_get_errors();

return array('#type' => 'ajax', '#commands' => $commands);

为了安全起见,核心_form_validate()功能检查元素的#options密钥是否已更改原始版本(设置)中的内容。通过调用drupal_get_messages()form_get_errors()我们基本上告诉Drupal在运行我们的Ajax请求时忽略任何错误/消息。:)


错误消息消失了,但是select元素仍然包含错误类,如何删除或防止这种情况发生?
Tejas Vaidya

这与Drupal等效,是将胶带贴在车辆仪表板上的警告灯上。
Frank Robert Anderson
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.