web-dev-qa-db-ja.com

jQueryを使用して、公開されているフォーム選択オプションを変更します。エラー:「不正な選択が検出されました。」検証をバイパスする方法は?

3つの公開フィルター(製造元、タイプ、モデル)、3つのオプションリスト(プリンターボキャブラリーへの用語参照)があるビューがあります。

語彙:プリンター(3レベル)

-- HP           
---- xxx     
------ xxxx  
-- Apple
---- xxxx
------ xxxxxx
-- Dell
---- xxxx
------- xxxxx
-- ...
-- ...
(thousands of terms)

Form API AJAXはビューの公開フォームでは機能しないため、公開されたフォームフィールドに対してそれらを依存選択することができません。したがって、jQueryを使用して公開フォームフィールドを「依存選択/カスケード選択」。

enter image description here

基本的に、まず、views_exposed_form_alter()のすべてのオプションを空にします。

$form['manufacturer_id']['#options'] = $form['type_id']['#options'] = $form['model_id']['#options'] = array();

次に、それに応じてオプションリストにjQueryコードを入力します。

しかし、「違法な選択が検出されました」と表示されます。ページの読み込み、フォームの送信時。 Drupalフォーム検証メカニズムにより、フォームの送信は禁止されています。

enter image description here

私がフォームのオプションを削除したため、jQueryによって生成されたオプションが元のフォームデータに付属していないことをフォームの検証が検出します。選択ボックスの値が、定義されたオプションに存在しません。

だから私はとしてフォームの検証でフォームの検証を削除しようとしました:

unset($form['#validate']);

それでも機能しない場合は、不正な選択エラーが残ります。

============更新済み=================

以下の@kiamlalunoの回答に触発されて、私が思いついた唯一の解決策は、コアをハック/パッチすることです。これが私がしたことです:

編集済み/includes/form.inc:(2014年の行)

enter image description here

私はコードを削除しました:

$element['#needs_validation'] = TRUE;

追加:

// if not these fields, mark for validation as usual. 
// so if are these fields, validation will be passed. 

if ($element['#name'] != 'manufacturer_id'  && 
    $element['#name'] != 'type_id'          && 
    $element['#name'] != 'model_id' ) {

  $element['#needs_validation'] = TRUE;
}

機能し、公開されたフォーム選択オプションは検証をバイパスしました。

しかし私の解決策は非常に醜いコアを変更しました。

コアに触れずに他の解決策はあるのでしょうか?これらの公開フォームフィールドの検証をバイパスするにはどうすればよいですか?

ありがとう!

4
gilzero

これらのエラーを示す関数は _ form_validate() で、次のコードが含まれています。

_  // Validate the current input.
  if (!isset($elements['#validated']) || !$elements['#validated']) {
    // The following errors are always shown.
    if (isset($elements['#needs_validation'])) {

      // ...

      if (isset($elements['#options']) && isset($elements['#value'])) {
        if ($elements['#type'] == 'select') {
          $options = form_options_flatten($elements['#options']);
        }
        else {
          $options = $elements['#options'];
        }
        if (is_array($elements['#value'])) {
          $value = in_array($elements['#type'], array('checkboxes', 'tableselect')) ? array_keys($elements['#value']) : $elements['#value'];
          foreach ($value as $v) {
            if (!isset($options[$v])) {
              form_error($elements, $t('An illegal choice has been detected. Please contact the site administrator.'));
              watchdog('form', 'Illegal choice %choice in !name element.', array('%choice' => $v, '!name' => empty($elements['#title']) ? $elements['#parents'][0] : $elements['#title']), WATCHDOG_ERROR);
            }
          }
        }

        // ...
      }
_

フォームに検証ハンドラがあるかどうかにかかわらず、関数は常に実行されます。

_$form['#needs_validation']_をFALSEに設定することもできますが、 _ form_builder_handle_input_element()TRUEに設定します。関数は form_builder() から呼び出され、次に drupal_process_form() または drupal_rebuild_form() から呼び出されます。

_  // Mark all posted values for validation.
  if (isset($element['#value']) || (!empty($element['#required']))) {
    $element['#needs_validation'] = TRUE;
  }
_

_form_builder_handle_input_element()が呼び出された後、form_builder()は、フォーム要素に設定された任意の #process 関数を呼び出します。

_  // Handle input elements.
  if (!empty($element['#input'])) {
    _form_builder_handle_input_element($form_id, $element, $form_state);
  }
  // Allow for elements to expand to multiple elements, e.g., radios,
  // checkboxes and files.
  if (isset($element['#process']) && !$element['#processed']) {
    foreach ($element['#process'] as $process) {
      $element = $process($element, $form_state, $form_state['complete form']);
    }
    $element['#processed'] = TRUE;
  }
_

また、フォーム要素に設定された #after_build 関数を呼び出します。

_  // The #after_build flag allows any piece of a form to be altered
  // after normal input parsing has been completed.
  if (isset($element['#after_build']) && !isset($element['#after_build_done'])) {
    foreach ($element['#after_build'] as $function) {
      $element = $function($element, $form_state);
    }
    $element['#after_build_done'] = TRUE;
  }
_

次のようなコードを実行する_#after_build_関数を設定できます。

_function mymodule_remove_validation($form_element) {
  unset($form_element['#needs_validation']);

  return $form_element;
}
_

unset($form_element['#needs_validation'])ではなく_form_validate()のifステートメントがisset($elements['#needs_validation'])をチェックするため、私は!empty($elements['#needs_validation'])を使用しています。

このように、フォーム要素は_#needs_validation_をTRUEに設定せず、Drupalはフォーム要素の戻り値をチェックしません。取得できる値、またはテキストフィールド文字列の長さが必要以上に長い。
フォーム検証ハンドラが実行されるのを避けられないと考えています。

8
kiamlaluno

Form_alterではなく、テーマ機能に空の '#options'が必要です。この場合、検証では「不正な選択エラー」は表示されません。

まず、views_exposed_form_alter()で、カスタムテーマ関数を選択に追加します。

$form['manufacturer_id']['#theme'][] = 'select_empty';
$form['type_id']['#theme'][] = 'select_empty';
$form['model_id']['#theme'][] = 'select_empty';

次に、モジュールまたはtemplate.phpファイルで新しいテーマ関数を作成します。

function THEME_NAME_theme($existing, $type, $theme, $path) {
  return array(
    'select_empty' => array(
      'render element' => 'element',
     ),
  );
}

function THEME_NAME_select_empty($vars) {
  // Empty select values and add one fake option for correct theming.
  $vars['element']['#options'] = array(
    'All' => t('All'),
  );

  // return default select.
  return theme('select', $vars) 
}
4
Eugene Fidelin

IIRC、Drupal 6.から始まるフォームAPIの検証を無効にすることはできません。Drupalでオプションを空にする代わりに、jQueryでそれらを空にすることができます。このようにして、オプションは= Drupal側で、検証エラーはトリガーされません。

1
vamur

ハードパーツが更新され、使用可能な色が追加され、AJAXを通じてフィルターの形状が変更されます。 AJAX UIに基づいて値を更新するように公開されたフィルターに指示することはできますが、UIは素晴らしいです。残念ながら、それはまだ不可能です。実際、公開することはできません。動的な値を提供するためのフィルターは、あらゆる種類を検討するのに論理的です。AJAXを介して自身を更新する必要があるため、変更できない場合 HPE0-Y53 PDF Dumps

0
billiam30