Drupal 7 Form API: Sử dụng #states cho multiple conditionals (AND, OR and XOR)

Drupal 7 Form API: Sử dụng #states cho multiple conditionals (AND, OR and XOR)

I've been playing with D7 forms lately and have found #states to be somewhat challenging due to lack of documentation on Form API page.
I've poked around a bit and decided to write a blog with my findings in case someone else is in need of this info down the road.
If you are looking for a robust solution for conditional fields, I would suggest looking into conditional fields or a more lightweight approach field conditional states (thanks for the comment Arjan and rooby).

If you have a simple, one off case where you have a conditional field and are reluctant to introduce 2-3k lines of code, you can use hook_form_alter() and #states API.
For this example I will use a very simple content type, Item, with following fields:

Title (title) [text]
Item Type (field_item_type) [select_list]:

    tv_show|TV Show
    movie|Movie
    banana|Banana for Scale
    truck|Truck

Format (field_format) [select_list]:

    video_dvd|DVD
    video_bluray|Blu-Ray
    video_3d|3D Blu-Ray

So I want to hide format field by default and display it only in case we are creating an Item of type TV Show or Movie.
I've created a simple module with the form alter that looks like this:

<?php
 
/**
 *  Implements hook_form_alter().
 */
function mtm_formapi_form_alter(&$form, &$form_state, $form_id) {
  if ($form_id == 'item_node_form') {
    $form['field_format']['#states'] = array(
      'visible' => array(
        ':input[name="field_item_type[und]"]' => array('value' => 'tv_show'),
      ),
    );
  }
}

The above code is pretty much it when it comes to Form API documentation on #states.
What it does is display field_format if the item type is TV Show, that is if :input[name="field_item_type[und]"] selector matches tv_show, otherwise it hides the format field.
But what about if there is more than one valid condition or if we need to meet multiple conditions?
Unfortunately, this is where things get a bit chaotic. There is not a common pattern that you can follow. Instead, you will need to change your strategy a bit depending on what your need is.
In case where you have multiple conditions which all need to be met, you can follow the pattern established in #state API docs:

    '[field-selector]' => array('[evaluate]'),
    '[field-selector2]' => array('[evaluate]'),
    ...
<?php
 
/**
 *  Implements hook_form_alter().
 */
function mtm_formapi_form_alter(&$form, &$form_state, $form_id) {
  if ($form_id == 'item_node_form') {
    $form['field_format']['#states'] = array(
      'visible' => array(
        ':input[name="field_item_type[und]"]' => array('value' => 'tv_show'),
        '#edit-title' => array('value' => 'test'),
      ),
    );
  }
}

The above will only show format field if title is test AND Item type is TV Show.
However, our original task was to display format if our Item type is TV Show OR Movie. The pattern in the docs will not work in this case.
Instead the pattern is the following:

    array('[field-selector]' => array('[evaluate]')),
    '[OR/XOR]',
    array('[field-selector2]' => array('[evaluate]')),
    ...
<?php
 
/**
 *  Implements hook_form_alter().
 */
function mtm_formapi_form_alter(&$form, &$form_state, $form_id) {
  if ($form_id == 'item_node_form') {
    $form['field_format']['#states'] = array(
      'visible' => array(
        array(
          array(':input[name="field_item_type[und]"]' => array('value' => 'tv_show')),
          'or',
          array(':input[name="field_item_type[und]"]' => array('value' => 'movie')),
        ),
      ),
    );
  }
}

Note above, we are using indexed instead of associative array and each individual statement is wrapped in an array.
The same pattern will work for XOR statements, all you have to do is replace 'or' with 'xor'. In addition, OR condition is implied when using the pattern above. That is, if I were to omit 'or' in the previous statement, the code would still behave as expected.

The support for OR and XOR came a bit latter, thus the chaos in the pattern and documentation.
One thing to keep in mind, if you are using jquery_update 1.7 and are using the OR and XOR, make sure you update it to the latest version as it overrides the form states.js and 1.7 doesn't support OR/XOR's.

 

Bạn thấy bài viết này như thế nào?: 
No votes yet
Ảnh của Tommy Tran

Tommy owner Express Magazine

Drupal Developer having 9+ year experience, implementation and having strong knowledge of technical specifications, workflow development. Ability to perform effectively and efficiently in team and individually. Always enthusiastic and interseted to study new technologies

  • Skype ID: tthanhthuy

Tìm kiếm bất động sản

 

Advertisement

 

jobsora

Dich vu khu trung tphcm

Dich vu diet chuot tphcm

Dich vu diet con trung

Quảng Cáo Bài Viết

 
LibreSource

Giới thiệu 7 Control Systems

If you’ve ever collaborated with other people on a project, you know the frustration of constantly swapping files. Some do it by email, some through file upload services and some by other methods. It’s a pain in the neck, and every designer and developer knows it. Revision control is an excellent way to combat the problem of sharing files between workers.

 CEO Facebook đã bay từ Lào Cai về lại Hà Nội

CEO Facebook đã bay từ Lào Cai về lại Hà Nội

Theo lái xe của công ty du lịch Đức Minh chở đoàn từ khách sạn Topas về thành phố Lào Cai từ 8 giờ 30 phút nhưng do yêu cầu đi chậm nên 10 giờ 30 đoàn mới tới vị trí...

Hội trợ triển lãm Palme 2013 chính thức khai mạc

Hội trợ triển lãm Palme 2013 chính thức khai mạc

Ngày 5/11, triển lãm Quốc tế lần thứ 3 tại Việt Nam về Thiết bị Nghe - Nhìn, Âm thanh - Ánh sáng chuyên nghiệp đã trở lại TPHCM sau 1 năm vắng bóng.

Công ty diệt chuột T&C

 

Diet con trung