1

選択ボックスで最初に選択したコンテンツ タイプ名のすべての日付フィールドを 2 番目の選択ボックスに入力しようとしています。$form_state で選択した値をフェッチするために ajax_callback を使用しています。エラーが発生していますが、その理由を特定できません。誰でも助けることができますか?

これは私のカスタム モジュール コードです。

function mymodule_settings($form, &$form_state){
  $content_type_options = array();
  $result = db_query("SELECT * FROM {node_type}");  
  foreach($result as $record){
    $content_type_options[$record->type]  =  $record->name;  
  }
  $form = array();
  $form['content_type'] = array(
    '#title'  => t('Content Types'),
    '#description'  => t('Select a content type.'),
    '#type' => 'select',
    '#options'  => $content_type_options,
    '#ajax' => array(
      'event' => 'change',
      'wrapper' => 'reg-start-date',
      'callback' => 'mymodule_datefields_ajax_callback',
      'method' => 'replace',
    ),
  );
  $form['checkboxes_fieldset'] = array(
    '#title' => t("Start Date"),
    '#prefix' => '<div id="reg-start-date">',
    '#suffix' => '</div>',
    '#type' => 'select',
    '#description' => t('Select the date field'),
  );
  $form['submit'] = array(
    '#type' => 'submit',
    '#value'  => t('Save'),
  );
  return $form;
}

function mymodule_datefields_ajax_callback($form, $form_state) {
  $fieldname = $form_state['triggering_element']['#value'];

  $field_query = db_query("SELECT fc.field_name FROM {field_config} fc, {field_config_instance} fci
                          WHERE fc.field_name = fci.field_name
                          AND fc.type = 'datetime'
                          AND fci.bundle = '".$fieldname."'");
  $datefield_options = array();
  foreach($field_query as $record){
    $datefield_options = $record;
  }
  return $datefield_options;
  //dpm($form_state, 'AJAX $form_state');
}

これがポップアップで表示されるエラーです-

AJAX HTTP エラーが発生しました。HTTP Result Code: 200 デバッグ情報が続きます。パス: /module_dev/?q=system/ajax StatusText: OK ResponseText: Fatal error: Cannot use object of type stdClass as array in /var/www/module_dev/includes/common.inc 行 5786

/var/www/module_dev/includes/common.inc の 5786 行目を調べたところ、そこにあるコードを見つけました。

function drupal_render(&$elements) {
  // Early-return nothing if user does not have access.
  if (empty($elements) || (isset($elements['#access']) && !$elements['#access'])) {
    return;
  }

  // Do not print elements twice.
  if (!empty($elements['#printed'])) {
    return;
  }

  // Try to fetch the element's markup from cache and return.
  if (isset($elements['#cache'])) {
    $cached_output = drupal_render_cache_get($elements);
    if ($cached_output !== FALSE) {
      return $cached_output;
    }
  }

  // If #markup is set, ensure #type is set. This allows to specify just #markup
  // on an element without setting #type.
  if (isset($elements['#markup']) && !isset($elements['#type'])) {
    $elements['#type'] = 'markup';
  }

  // If the default values for this element have not been loaded yet, populate
  // them.
  if (isset($elements['#type']) && empty($elements['#defaults_loaded'])) {
    $elements += element_info($elements['#type']);
  }

  // Make any final changes to the element before it is rendered. This means
  // that the $element or the children can be altered or corrected before the
  // element is rendered into the final text.
  if (isset($elements['#pre_render'])) {
    foreach ($elements['#pre_render'] as $function) {
      if (function_exists($function)) {
        $elements = $function($elements);
      }
    }
  }

  // Allow #pre_render to abort rendering.
  if (!empty($elements['#printed'])) {
    return;
  }

  // Get the children of the element, sorted by weight.
  $children = element_children($elements, TRUE);

  // Initialize this element's #children, unless a #pre_render callback already
  // preset #children.
  if (!isset($elements['#children'])) {
    $elements['#children'] = '';
  }
  // Call the element's #theme function if it is set. Then any children of the
  // element have to be rendered there.
  if (isset($elements['#theme'])) {
    $elements['#children'] = theme($elements['#theme'], $elements);
  }
  // If #theme was not set and the element has children, render them now.
  // This is the same process as drupal_render_children() but is inlined
  // for speed.
  if ($elements['#children'] == '') {
    foreach ($children as $key) {
      $elements['#children'] .= drupal_render($elements[$key]);
    }
  }

  // Let the theme functions in #theme_wrappers add markup around the rendered
  // children.
  if (isset($elements['#theme_wrappers'])) {
    foreach ($elements['#theme_wrappers'] as $theme_wrapper) {
      $elements['#children'] = theme($theme_wrapper, $elements);
    }
  }

  // Filter the outputted content and make any last changes before the
  // content is sent to the browser. The changes are made on $content
  // which allows the output'ed text to be filtered.
  if (isset($elements['#post_render'])) {
    foreach ($elements['#post_render'] as $function) {
      if (function_exists($function)) {
        $elements['#children'] = $function($elements['#children'], $elements);
      }
    }
  }

  // Add any JavaScript state information associated with the element.
  if (!empty($elements['#states'])) {
    drupal_process_states($elements);
  }

  // Add additional libraries, CSS, JavaScript an other custom
  // attached data associated with this element.
  if (!empty($elements['#attached'])) {
    drupal_process_attached($elements);
  }

  $prefix = isset($elements['#prefix']) ? $elements['#prefix'] : '';
  $suffix = isset($elements['#suffix']) ? $elements['#suffix'] : '';
  $output = $prefix . $elements['#children'] . $suffix;

  // Cache the processed element if #cache is set.
  if (isset($elements['#cache'])) {
    drupal_render_cache_set($output, $elements);
  }

  $elements['#printed'] = TRUE;
  return $output;
}
4

1 に答える 1

0

<div>AJAX コールバックが返す必要があるのは、CSS ID が #ajax[wrapper] として設定されているタグのコンテンツを置き換えるフォーム要素のレンダリング配列です。AJAX コールバックが返すのはオブジェクトの配列です。これはレンダリング API が期待するものではありません。(レンダリング API は配列を使用します。) そのため、オブジェクトを配列として使用できないというエラーが表示されます。

AJAX を使用したフォーム ビルダーの例としてajax_example_simplest()を参照してください。特に、その AJAX コールバックajax_example_simplest_callback()を参照してください。

つまり、 のコードはmymodule_datefields_ajax_callback()次のようになります。

function mymodule_datefields_ajax_callback($form, $form_state) {
  return $form['checkboxes_fieldset'];
}

フォーム ビルダーは、次のコードを使用する必要があります。

function mymodule_settings($form, &$form_state){
  $content_type_options = array();
  $result = db_query("SELECT * FROM {node_type}");  
  foreach ($result as $record) {
    $content_type_options[$record->type]  =  $record->name;  
  }

  // $form is already passed as argument; you don't need to initialize it to an empty array.
  // $form = array();

  $form['content_type'] = array(
    '#title'  => t('Content Types'),
    '#description'  => t('Select a content type.'),
    '#type' => 'select',
    '#options'  => $content_type_options,
    '#ajax' => array(
      'event' => 'change',
      'wrapper' => 'reg-start-date',
      'callback' => 'mymodule_datefields_ajax_callback',
      'method' => 'replace',
    ),
  );

  // An AJAX request call to the form builder function has been done.
  if (!empty($form_state['values']['content_type'])) {
    // Use $form_state['values']['content_type'] to get the option list.
    // Set the value of $date_options with that list.
    $field_query = db_query("query to execute");
    $date_options = array();

    foreach ($field_query as $record) {
      $date_options[$record->field_name] = $record->field_name;
    }
  }
  else {
    $date_options = array();
  }

  $form['checkboxes_fieldset'] = array(
    '#title' => t("Start Date"),
    '#prefix' => '<div id="reg-start-date">',
    '#suffix' => '</div>',
    '#type' => 'select',
    '#options' => $date_options,
    '#description' => t('Select the date'),
  );

  $form['submit'] = array(
    '#type' => 'submit',
    '#value'  => t('Save'),
  );

  return $form;
}

$date_optionsフォーマットの配列ですvalue => string_to_show。に使用したのと同じ形式です$content_type_options

于 2013-01-21T09:58:46.450 に答える