「不正な選択が検出されました...」というエラーを解決します


7

私は以下のようなコードを書いており、すべて正常に動作しますが、フォームを送信しているときに以下のエラーが発生します。最初のドロップダウンの選択に基づいて2番目のドロップダウンをフィルタリングしようとしています。

違法な選択が検出されました。サイト管理者に連絡してください。

どうすればそのエラーを克服できますか?

function dynamic_location_dropdown_form_alter(&$form, $form_state, $form_id) {
  if($form_id == 'product_node_form') {

  $location_options = array();

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

  $location_options = dynamic_location_dropdown_locations($destination);

  $form['field_destination']['und']['#ajax'] = array(
    'event' => 'change',
    'wrapper' => 'squadron-wrapper',
    'callback' => 'dynamic_location_dropdown_ajax_callback',
    'method' => 'replace',
  );
  $form['field_product_location']['#validated'] = true;
  $form['field_product_location']['und']['#prefix'] = '<div id="squadron-wrapper">';
  $form['field_product_location']['und']['#suffix'] = '</div>';
  $form['field_product_location']['und']['#options'] = $location_options;
  }
}

function dynamic_location_dropdown_ajax_callback($form, $form_state) {
  $country_id = $form['field_destination']['und']['#value'];
  $form['field_product_location']['#validated'] = true;
  $form['field_product_location']['und']['#options'] =  dynamic_location_dropdown_locations($country_id);

  return $form['field_product_location'];
}

function dynamic_location_dropdown_locations($destination_id) {
  $nodes = array();
  $nodes[''] = '- None -';
  if($destination_id != '') {
    $select = db_query("
      SELECT node.title AS node_title, node.nid AS nid, node.created AS node_created
      FROM {node} node
      LEFT JOIN {field_data_field_location_country} field_data_field_location_country 
      ON node.nid = field_data_field_location_country.entity_id 
      AND (field_data_field_location_country.entity_type = 'node' 
      AND field_data_field_location_country.deleted = '0')
      WHERE (( (node.status = '1') 
      AND (node.type IN  ('location')) 
      AND (field_data_field_location_country.field_location_country_nid = $destination_id)))
      ORDER BY node_title ASC
    ");
    $nodes[''] = '- None -';
    foreach ($select as $node) {
      $nodes[$node->nid] = $node->node_title;
    }
  }

  return $nodes;
}

まあ、あなたはすでにそれを処理'#validated' => TRUEするはずのものを使っています。だから私の推測では、いくつかのプロパティには「und」キーがあり、「#validated」キーを使用するフォーム配列にはない...?
30等しい

回答:


8

この問題は、Drupal 7のAJAX Formsに文書化されているFAPI AJAXの要件が原因である可能性が高いですが、簡単に見逃される可能性があります。

フォームの変更は、フォームビルダー関数(この例では、ajax_example_autocheckboxes())でのみ行う必要があります。そうしないと、検証が失敗します。コールバック関数は、フォームやその他の状態を変更してはなりません。

[#options]AJAXコールバックでフォーム要素を設定しているという事実は間違いなく問題です。AJAXコールバックは、フォームを変更するのではなく、印刷する配列またはHTMLのみを返す必要があります。そのコールバックにはreturnステートメントのみを含める必要があります。

フォームへの変更は、form_alterで行う必要があります。また、最初のドロップダウンに値が選択されているかどうかを確認するには、form_state配列を使用する必要があります。これは、AJAXリクエスト中に更新されます。

FAPIでのAJAXの詳細については、サンプルモジュールとこれらのページを参照することをお勧めします。それは間違いなくトリッキーになる可能性があります。


また、例として、フォームの動的選択リスト(依存ドロップダウン)を参照してください(ただし、 " return $form['squadron_wrapper']"を使用してAJAX応答を小さくすることを検討してください)。
トップマスター、

2

以下のメソッドは、ajaxを介して値が追加されたフィールドのエラーのみを無視するために使用できます。以下
のコードに従って、エラーを発生させるフィールド要素を入力して、2番目のドロップダウンの値がajaxの使用による最初のドロップダウンはエラーを表示しません。

/**
 * Custom Form Validation.
 * Removes all form validation errors caused by a 'foo][bar' form element.
 */
function my_module_form_validate($form, &$form_state) {
  $errors = form_get_errors();
  if ($errors) {
    // Clear errors.
    form_clear_error();
    // Clear error messages.
    $error_messages = drupal_get_messages('error');
    // Initialize an array where removed error messages are stored.
    $removed_messages = array();


// Remove all errors originated by the 'foo][bar' element.
    foreach ($errors as $name => $error_message) {
      if ($name == 'foo][bar') {
        $removed_messages[] = $error_message;
        unset($errors[$name]);
      }
    }


// Reinstate remaining errors.
    foreach ($errors as $name => $error) {
      form_set_error($name, $error);
      // form_set_error() calls drupal_set_message(), so we have to filter out
      // these from the error messages as well.
      $removed_messages[] = $error;
    }


// Reinstate remaining error messages (which, at this point, are messages that
    // were originated outside of the validation process).
    foreach (array_diff($error_messages['error'], $removed_messages) as $message) {
      drupal_set_message($message, 'error');      
    }
  }
}

1

これはコアバグhttps://www.drupal.org/node/153774のようであり、ここで説明されている解決策は実際により多くの問題を引き起こします。

#ajaxがselect要素に使用されている場合、複数のオプションが選択されていると、「不正な選択エラー」が生成されます。しかし、なぜ?少し調べた結果、#ajaxが有効になっていると、select要素がarray(200 => 200、250 => 250)ではなくarray(200,250)のような値を送信することが判明したため、内部のオプション検証コードで問題が発生します_form_validate関数を使用すると、選択したオプションを使用可能なオプションと照合できなくなります。コードは次のとおりです。これは、複数のオプションが選択され、#ajaxが使用されている場合にのみ発生します。修正は、検証前に送信された値を修正することです

このバグを自動的に回避するモジュールを作成しましたが、すべてのケースで機能するわけではありませんが、これを開始点として使用できる明確な回避策です。

https://www.drupal.org/sandbox/sinasalek/2312751

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