web-dev-qa-db-ja.com

ajaxによって読み込まれた選択フィールドでの最も単純な

Googleを検索しましたが、答えが見つかりません。 Stack Exchangeは私の最後の手段です。

私のフォームには、2つの選択フィールドがあります。

_$form['system']['foo'] = array(
  ...
  '#type' => 'select',
  '#options' => array('A', 'B', 'C'),
  ...
  '#ajax' => array(
    'event' => 'change',
    ...
    'method' => 'replace',
  ),
);

$form['system']['bar'] = array(
  ...
  '#type' => 'select',
  '#options' => array(),
  '#prefix' => ...
  '#suffix' => ...
);
_

ユーザーがfooフィールドのオプションのいずれかを選択した場合、barフィールドはajaxを介してオプションを動的にロードします。例:「A」がfooで選択されている場合、barフィールドは「aaa」、「bbb」、「ccc」などのオプションを生成し、ユーザーが選択できます。

このフォームは機能し、「Simpletest」を使用してユニットテストを提供する必要があります。

私のテストケースでは:

_$edit = array(
  'system[foo]' => 1, // value for 'A'
  'system[bar]' => 2, // value for 'bbb'
);
$this->drupalPost('mymodule/mypath', $edit, t('Submit'));
_

_system[bar]_を2に設定できないことを示すエラーが発生します(まだ2の値がないため?)

_system[foo]_を設定する前に、_system[bar]_でajax呼び出しをエミュレートする必要があります。

私はdrupalPostAjaxを試しました:

_$edit = array(
  'system[foo]' => 1, // value for A
);
$this->drupalPostAjax('mymodule/mypath', $edit, 'system[foo]');
_

ajaxで成功した結果が得られます。コードの次の行で、前のコードスニペットを使用してdrupalPost()をもう一度呼び出してみましたが、_system[bar]_を2に設定できないという同じエラーが表示されます。

どうすれば問題を解決できますか?それは私を大いに助けることができるので、サンプルコードを提供してください。


編集:

Ajaxは実際のページで機能します(つまり、値は_system['bar']_に動的にロードされます)。したがって、フォーム内のコードが機能していると想定できます。

ただし、ajaxがSimpletestから生成されたページ(sites/default/files/simpletest/verboseにあるページ)では機能しないことに気づきました。 GoogleのコンソールChromeはエラーを表示しません。Ajaxはステータス200を返しますが、応答はありません。

インストール時にデフォルトのテーマを使用しています。


編集:フォームとシンプルなコード

フォーム:znerolが投稿したフォームをコピーしました。

最も単純なコード:

_class MyModuleTestCase extends DrupalWebTestCase {
  protected $admin_user;

  public static function getInfo() {
    return array(
      'name' => 'Test Case name',
      'description' => 'Test Case Description',
      'group' => 'My Module',
    );
  }

  public function setUp() {
    // Enable module
    parent::setUp(array('mymodule'));

    // Get permissions
    $permissions = mymodule_get_permissions();
    // Permissions obtained correctly.

    // Create and login admin user
    $this->admin_user = $this->drupalCreateUser($permissions);
    $this->drupalLogin($this->admin_user);
  }

  // Test section
  public function testSystem() {
    $this->drupalGet('mymodule/mypath');
    $edit = array(
      'system[foo]' => 1, // Selects 'A'. Tested!
    );
    $this->drupalPostAjax(NULL, $edit, 'system[foo]');
    // Bar after ajax is loaded
    $edit = array(
      'system[bar]' => 1, // Selects 'aaa'
    );
    $this->drupalPost(NULL, $edit, t('Submit')); // Error here.
    $this->assertText(t('Submitted!'));
  }
}
_

ただし、simpletestを実行すると、simpletestは_system['bar']_を_1_(aaa)に設定できないと不平を言います。

Simpletestがajaxを呼び出す前に次の警告を表示することに気づきました。

未定義のオフセット:0通知drupal_web_test_case.php 2147 DrupalWebTestCase> drupalPostAJAX()

未定義のインデックス:drupal_web_test_case.php 2148 DrupalWebTestCase-> drupalPostAJAX()に注意してください

未定義のインデックス:#ajax Notice ajax.inc 379 ajax_form_callback()

_system['bar']_はajaxを介して動的にロードされるため、最初は空の配列array()があります。上記の警告から、_system['bar']_に一時オプションarray('1', '2')を追加してみました。同じエラーと警告が発生します。

4
Neigyl R. Noval

$pathパラメータをNULLに送信すると、同じフォームに送信されます。それ以外の場合、drupalPost/drupalPostAJAXはまずページを再度取得し、現在のフォームを再構築する代わりに新しいフォームを生成します。

次のテストはあなたが望むことをするはずです:

// First retrieve the page once
$this->drupalGet('mymodule/mypath');

// Set $path to NULL on subsequent requests to the same form
$edit = array('system[foo]' => 1);
$this->drupalPostAJAX(NULL, $edit, 'system[foo]');

$edit = array('system[bar]' => 2);
$this->drupalPost(NULL, $edit, t('Submit'));

テストケースは、次のフォームで実行すると成功します。

function mymodule_myform($form, &$form_state) {
  $foo_options = array('A', 'B', 'C');
  $foo_default = isset($form_state['values']['system']['foo']) ? $form_state['values']['system']['foo'] : NULL;

  $form['system']['#tree'] = TRUE;

  $form['system']['foo'] = array(
    '#type' => 'select',
    '#options' => $foo_options,
    '#default_value' => $foo_default,
    '#ajax' => array(
      'callback' => 'mymodule_myform_ajax_callback',
      'wrapper' => 'bar-div',
      'method' => 'replace',
    ),
  );

  $bar_choices = array(
    0 => array('aaa', 'bbb', 'ccc'),
    1 => array('ddd', 'eee', 'fff'),
    2 => array('ggg', 'hhh', 'iii'),
  );
  $form['system']['bar'] = array(
    '#prefix' => '<div id="bar-div">',
    '#suffix' => '</div>',
    '#type' => 'select',
    '#options' => isset($bar_choices[$foo_default]) ? $bar_choices[$foo_default] : array(),
  );

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

function mymodule_myform_ajax_callback($form, $form_state) {
  return $form['system']['bar'];
}
4
znerol

あなたの次のコードで私が気付いた1つのこと:

$form['system']['foo'] = array(
  ...
  '#type' => 'select',
  '#options' => array('A', 'B', 'C'),
  ...
  '#ajax' => array(
    'event' => 'change',
    ...
    'method' => 'replace',
  ),
);

$form['system']['bar'] = array(
  ...
  '#type' => 'select',
  '#options' => array(),
  '#prefix' => ...
  '#suffix' => ...
);

system[bar]フィールドが空の配列で初期化されました:array()。

そして、オプションを含まないそのフィールドの値を設定しようとしているよりも。私の推測では、system[bar]フィールドのオプションも初期化できますか。 barフィールドがajaxを介してオプションを動的にロードすることを述べたのは知っています。しかし、そのフィールドの値は、適切な結果セットで初期化されない限り設定できないと思います。

0
Ankit Agrawal