フォーム内の動的選択リスト(依存ドロップダウン)


28

Drupal 7を使用しています。選択リストのオプションを、フォーム内の別の選択リストで選択された値に依存するようにします。これは以前にも何度も質問されていたと思いますが、これを行う方法について明確な答えを見つけるのは困難です。

このフォームは、ユーザーが作業履歴を入力するためのものです。彼らは、飛行隊フィールドタイプへのノード参照である飛行隊を選択する必要があり、これはドロップダウンリストにあります。ただし、戦隊は都市のドロップダウンリストに依存しています。ユーザーは最初に都市を選択する必要があります。都市を選択すると、戦隊のオプションがフィルタリングされます。飛行隊コンテンツタイプでは、飛行隊にタグ付けされる都市の分類法を作成しました。

これを実行するための最善の方法(最も簡単な方法)についてのポインタ、または役立つオンラインの有用なリソースに非常に感謝します。

回答:


27

これを実現するには、Ajaxを使用できます。Drupal 7は現在、Ajaxを適切にサポートしています。最初の選択リスト(市)で、Ajax情報を追加する必要があります。次に、2番目の選択リストを最初の情報に基づいて入力できます。最初のオプションが選択されるまで、2番目の選択リストを非表示にすることもできます。その方法を少し説明します。最初に、基本フォームをセットアップします。

$form['city'] = array(
  '#type' => 'select',
  '#title' => t('City'),
  '#options' => $options,
  '#ajax' => array(
    'event' => 'change',
    'wrapper' => 'squadron-wrapper',
    'callback' => 'mymodule_ajax_callback',
    'method' => 'replace',
  ),
);
$form['squadron_wrapper'] = array('#prefix' => '<div class="squadron-wrapper">', '#suffix' => '</div>');
$form['squadron_wrapper']['squadron'] = array(
  '#type' => 'select',
  '#title' => t('Squadron'),
  '#options' => $squadron_options,
);

これは要素の基本的なセットアップにすぎません。ここで、どのオプションが戦隊に入るべきかを決定する方法が必要になります。最初に、「city」選択リストでAjaxコールバックを識別する必要があります。ほとんどの場合、ajax要素をラップする要素、この場合は$ formを返すことができます。

function mymodule_ajax_callback($form, $form_state) {
  return $form;
}

ここで、「都市」選択リストが変更されると、フォームの戦隊ラッパー部分が再構築されます。「市」の値は$ form_state ['values']になります。そのため、フォームを再構築するときに、「city」の値に基づいて選択リストに与えるオプションを決定する必要があります。

// Get the value of the 'city' field.
$city = isset($form_state['values']['city']) ? $form_state['values']['city'] : 'default';
switch ($city) {
  case 'default':
    // Set default options.
    break;
  case 'losangeles':
    // Set up $squadron_options for los angeles.
    break;
}

// If you want to hide the squadron select list until a city is
// selected then you can do another conditional.
if ($city !== 'default') {
  $form['squadron_wrapper']['squadron'] = array(
    '#type' => 'select',
    '#title' => t('Squadron'),
    '#options' => $squadron_options,
  );
}

6
サンプルは、Examplesモジュールにあります(「AJAX Examples」→「Dependent dropdown」)。階層選択モジュールでも確認できます。
kalabro

ちなみに、代わりにマルチステップ形式でこれを行うことができますが、私はそれがあなたが探しているもののように聞こえるとは思いませんでした。また、^良い電話!サンプルモジュールは、この種のことを学ぶのに最適です。
ヨルドジュース

@jordojuiceご回答ありがとうございます。現在取り組んでいます。上記のコードの3番目の例(// Get the value ...)で、コードのこの部分をどの関数に入れますか?_ajax_callback関数に入れますか?ありがとう
ベン

私はこれのためにサンプルモジュールに従いましたが、最初のドロップダウンでアイテムを選択するたびにエラーが発生しました:警告:array_values()はパラメーター1が配列であり、_field_filter_items()で指定された文字列が必要です(I:\ My Documentsの525行目) \ web \ xampp \ htdocs \ mysite \ modules \ field \ field.module)。私はカスタムオーバーライドモジュールで書いたこのajax依存のドロップダウンと組み合わせてマルチステップフォームを使用しています。最初の値に基づいて2番目のddの値が変更されますが。それはただの警告ですが、いらいらします...誰かがその警告を取り除くのを手伝ってくれませんか?ありがとう!
1月

2このコードと@Benで機能するようになったコードの重要な違い。#suffixはidを使用し、ajaxコールバックはフォーム全体ではなくフォーム要素を返すことに注意してください。それ以外は、これはとても役に立ちました!
ウォルファ東

11

上記のjordojuiceに感謝します。彼の助けを借りて、解決策を見つけることができました。また、http: //public-action.org/content/drupal-7-form-api-dependent-lists-and-ajax-form-submissionの例を参照しました。最終的に、カスタムモジュールで機能する以下のコードを使用しました。何らかの理由で、$ form_stateの値で値を見つけることができませんでしたが、$ formで値を見つけることができました。最後に、テストしたときに、Drupalがドロップダウンで不正な選択を検出したというエラーメッセージが表示されました。form.incの1290行目をコメントアウトすることでこれを実現しました。

form_error($elements, $t('An illegal choice has been detected. Please contact the site administrator.'));

最終的に使用したコードは次のとおりです。

<?php

function sappers_squadron_form_work_history_node_form_alter(&$form, &$form_state) {     
        //echo '<pre>';
        //print_r ($form);
        //echo '</pre>';

        $squadron_options = array();

        if(isset($form['field_wkhist_city']['und']['#default_value'][0])) {
            $city = $form['field_wkhist_city']['und']['#default_value'][0];
        }
        else {
            $city = 0;
        }

        $squadron_options = sappers_squadron_squadrons($city);

        $form['field_wkhist_city']['und']['#ajax'] = array(
            'event' => 'change',
            'wrapper' => 'squadron-wrapper',
            'callback' => 'sappers_squadron_ajax_callback',
            'method' => 'replace',
        );

        $form['field_squadron']['und']['#prefix'] = '<div id="squadron-wrapper">';
        $form['field_squadron']['und']['#suffix'] = '</div>';
        $form['field_squadron']['und']['#options'] = $squadron_options;
}


function sappers_squadron_ajax_callback($form, $form_state) {   
    $city = $form['field_wkhist_city']['und']['#value'];

    $form['field_squadron']['und']['#options'] = sappers_squadron_squadrons($city);

    return $form['field_squadron'];
}


function sappers_squadron_squadrons($city) {
    $nodes = array();

    $select = db_query("SELECT node.title AS node_title, node.nid AS nid FROM  {node} node INNER JOIN {taxonomy_index} taxonomy_index ON node.nid = taxonomy_index.nid WHERE (( (node.status = '1') AND (node.type IN  ('squadron')) AND (taxonomy_index.tid = $city) )) ORDER BY node_title ASC");

    $nodes[]="";

    foreach ($select as $node) {
            $nodes[$node->nid] = $node->node_title;
    }

    return $nodes;
}

?>

不正な選択が検出されました。サイト管理者に連絡してください。上記を実装しようとしたときにエラーが発生しました。手伝ってもらえますか?
ハルシャル

@harshal-私は同じ問題を抱えていたので、答えで示した解決策を実装することで解決しました。上記を参照してください(form.incの変更)。これはちょっとしたハックですが、私にとってはうまくいきました。
ベン

@harshal-おそらくより良い解決策は、以下のHackerによるものです。
ベン

1

コードの行を入れますすなわち
$nodes[''] = '- None -';

 $nodes = array();

ウルで sappers_squadron_squadrons function 、それはあなたのエラーを解決します

form_error($elements, $t('An illegal choice has been detected. Please contact the site administrator.'));


1

「不正な選択が検出されました。サイト管理者に連絡してください」の根本原因。値0が追加された空の文字列$nodes[]="";は、field_squadronフィールドでは無効です。

Advance PHP Programming and Developmentを参照してください。ただし、DANGEROUS_SKIP_CHECKおよび検証済みフラグはD7で非推奨になったことに留意してください。

その行を削除した後、エラーはなくなりました。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.