Drupal 7 Form API - 自定义自动完成过滤器

时间:2014-03-12 13:03:37

标签: drupal

使用D7表单API,我需要创建一个分层的过滤器集,每个过滤器都具有前一个过滤器的依赖关系。当在其中一个过滤器上进行选择时,线下的所有过滤器将根据链上的选择自动更新。看起来很直接,但还有一点点。

举个例子,假设我有一个数据库,我想要显示+ 75k的产品记录。

  • 过滤器1 - 品牌(10k可能的选项)
  • 过滤器2 - 产品(20k可能的选项)
  • 过滤器3 - 名称(75k可能的选项)

显然我无法在每个select-multi中显示所有选项,所以这就是我设想它的工作方式:

  1. 页面加载,所有过滤器都为空
  2. 每个过滤器上面都有一个小文本输入。键入该字段自动完成,但结果将转储到select-multi输入。
  3. 用户从刚刚填充的列表中选择一个选项。
  4. 线下的所有过滤器都会自动填充,并通过链条上的选择进行细化。
  5. 我一直在看D7表单api,我找不到任何关于这种功能的提及。我知道有#ajax和#state回调,但文本输入自动完成填充链中的select-multi和触发事件有点模糊。

    如果有帮助,我已经使用jQuery构建了这整个功能。我现在的目标是使用适当的表单API将其移植到Drupal中。

2 个答案:

答案 0 :(得分:1)

我知道这已经很久了,但仍然会为寻求解决方案的其他人分享。您必须根据需要实现自己的每个自动完成功能的风格。需要注意的重要一点是使用先前过滤器中的值设置的autocomplete_path。休息应该是自我解释的。

// hook_menu would look something like this
function hook_menu() {
  $menu = array();
  $menu['hierarchical_filter'] = array(
    'title' => 'Autocomplete Ajax Cascading Form',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('hierarchical_filter_form'),
    'access callback' => TRUE,
  );
  $menu['country_list'] = array(
    'title' => 'Country List autocomplete',
    'page callback' => 'country_list_autocomplete',
    'access callback' => TRUE,
    'type' => MENU_CALLBACK,
  );
  $menu['state_list'] = array(
    'title' => 'State List autocomplete',
    'page callback' => 'state_list_autocomplete',
    'access callback' => TRUE,
    'type' => MENU_CALLBACK,
  );
  $menu['city_list'] = array(
    'title' => 'City List autocomplete',
    'page callback' => 'city_list_autocomplete',
    'access callback' => TRUE,
    'type' => MENU_CALLBACK,
  );
  return $menu;
}
function country_list_autocomplete($string='') {
  $values = array('United States' => 'United States', 'South Africa' => 'South Africa', 'Russian Federation' => 'Russian Federation', 'Singapore' => 'Singapore', 'China' => 'China');
  $matches = array_filter($values, function($item) use($string) {
    if(stripos($item, $string) !== FALSE) return TRUE;
    return FALSE;
  });
  drupal_json_output($matches);
}
function state_list_autocomplete($country_code, $state='') {
  $values = array('South Africa' => array('Mpumalanga' => 'Mpumalanga', 'Gauteng' => 'Gauteng', 'Limpopo' => 'Limpopo', 'Northern Cape' => 'Northern Cape'),
    'United States' => array('Alabama'=>'Alabama', 'Arizona'=>'Arizona'));
  $matches = array_filter($values[$country_code], function($item) use($state) {
    if(stripos($item, $state) !== FALSE) return TRUE;
    return FALSE;
  });
  drupal_json_output($matches);
}
function city_list_autocomplete($state, $city='') {
  $values = array('northern cape' => array('Barkly West' => 'Barkly West', 'Campbell' => 'Campbell', 'Delportshoop' => 'Delportshoop'),
    'Alabama' => array('Butler'=>'Butler', 'Calera'=>'Calera', 'Helena'=>'Helena'));
  $matches = array_filter($values[$state], function($item) use($city) {
    if(stripos($item, $city) !== FALSE) return TRUE;
    return FALSE;
  });
  drupal_json_output($matches);
}
function hierarchical_filter_form($form, &$form_state) {
  $form = array();
  $form['country_list'] = array(
    '#type' => 'textfield',
    '#title' => 'Choose Country',
    '#autocomplete_path' => 'country_list',
    '#ajax' => array(
      'callback' => 'country_callback',
      'wrapper' => 'states_wrapper',
    ),
  );
  $form['state_list'] = array(
    '#type' => 'textfield',
    '#title' => 'Choose State',
    '#prefix' => '<div id="states_wrapper">',
    '#suffix' => '</div>',
  );
  if(isset($form_state['values']['country_list'])) {
    $form['state_list']['#autocomplete_path'] = 'state_list/'.$form_state['values']['country_list'];
    $form['state_list']['#ajax'] = array(
      'callback' => 'state_callback',
      'wrapper' => 'city_wrapper',
    );
  }
  $form['city_list'] = array(
    '#type' => 'textfield',
    '#title' => 'Choose City',
    '#prefix' => '<div id="city_wrapper">',
    '#suffix' => '</div>',
  );
  if(isset($form_state['values']['state_list'])) {
    $form['city_list']['#autocomplete_path'] = 'city_list/'.$form_state['values']['state_list'];
  }
  return $form;
}
function country_callback($form, &$form_state) {
  $commands = array();
  // On changing country, make sure state and city fields are reset
  $form['state_list']['#value'] = '';
  $form['city_list']['#value'] = '';
  $commands[] = ajax_command_replace('#states_wrapper', drupal_render($form['state_list']));
  $commands[] = ajax_command_replace('#city_wrapper', drupal_render($form['city_list']));
  return array('#type' => 'ajax', '#commands' => $commands);
}
function state_callback($form, &$form_state) {
  // On changing state, make sure city field is reset
  $form['city_list']['#value'] = '';
  return $form['city_list'];
}

// hook_menu would look something like this function hook_menu() { $menu = array(); $menu['hierarchical_filter'] = array( 'title' => 'Autocomplete Ajax Cascading Form', 'page callback' => 'drupal_get_form', 'page arguments' => array('hierarchical_filter_form'), 'access callback' => TRUE, ); $menu['country_list'] = array( 'title' => 'Country List autocomplete', 'page callback' => 'country_list_autocomplete', 'access callback' => TRUE, 'type' => MENU_CALLBACK, ); $menu['state_list'] = array( 'title' => 'State List autocomplete', 'page callback' => 'state_list_autocomplete', 'access callback' => TRUE, 'type' => MENU_CALLBACK, ); $menu['city_list'] = array( 'title' => 'City List autocomplete', 'page callback' => 'city_list_autocomplete', 'access callback' => TRUE, 'type' => MENU_CALLBACK, ); return $menu; } function country_list_autocomplete($string='') { $values = array('United States' => 'United States', 'South Africa' => 'South Africa', 'Russian Federation' => 'Russian Federation', 'Singapore' => 'Singapore', 'China' => 'China'); $matches = array_filter($values, function($item) use($string) { if(stripos($item, $string) !== FALSE) return TRUE; return FALSE; }); drupal_json_output($matches); } function state_list_autocomplete($country_code, $state='') { $values = array('South Africa' => array('Mpumalanga' => 'Mpumalanga', 'Gauteng' => 'Gauteng', 'Limpopo' => 'Limpopo', 'Northern Cape' => 'Northern Cape'), 'United States' => array('Alabama'=>'Alabama', 'Arizona'=>'Arizona')); $matches = array_filter($values[$country_code], function($item) use($state) { if(stripos($item, $state) !== FALSE) return TRUE; return FALSE; }); drupal_json_output($matches); } function city_list_autocomplete($state, $city='') { $values = array('northern cape' => array('Barkly West' => 'Barkly West', 'Campbell' => 'Campbell', 'Delportshoop' => 'Delportshoop'), 'Alabama' => array('Butler'=>'Butler', 'Calera'=>'Calera', 'Helena'=>'Helena')); $matches = array_filter($values[$state], function($item) use($city) { if(stripos($item, $city) !== FALSE) return TRUE; return FALSE; }); drupal_json_output($matches); } function hierarchical_filter_form($form, &$form_state) { $form = array(); $form['country_list'] = array( '#type' => 'textfield', '#title' => 'Choose Country', '#autocomplete_path' => 'country_list', '#ajax' => array( 'callback' => 'country_callback', 'wrapper' => 'states_wrapper', ), ); $form['state_list'] = array( '#type' => 'textfield', '#title' => 'Choose State', '#prefix' => '<div id="states_wrapper">', '#suffix' => '</div>', ); if(isset($form_state['values']['country_list'])) { $form['state_list']['#autocomplete_path'] = 'state_list/'.$form_state['values']['country_list']; $form['state_list']['#ajax'] = array( 'callback' => 'state_callback', 'wrapper' => 'city_wrapper', ); } $form['city_list'] = array( '#type' => 'textfield', '#title' => 'Choose City', '#prefix' => '<div id="city_wrapper">', '#suffix' => '</div>', ); if(isset($form_state['values']['state_list'])) { $form['city_list']['#autocomplete_path'] = 'city_list/'.$form_state['values']['state_list']; } return $form; } function country_callback($form, &$form_state) { $commands = array(); // On changing country, make sure state and city fields are reset $form['state_list']['#value'] = ''; $form['city_list']['#value'] = ''; $commands[] = ajax_command_replace('#states_wrapper', drupal_render($form['state_list'])); $commands[] = ajax_command_replace('#city_wrapper', drupal_render($form['city_list'])); return array('#type' => 'ajax', '#commands' => $commands); } function state_callback($form, &$form_state) { // On changing state, make sure city field is reset $form['city_list']['#value'] = ''; return $form['city_list']; } 希望这会对某人有所帮助。

答案 1 :(得分:0)

创建论坛函数让我们说my_module_filters_form比使用hook_menu添加菜单回调

function my_module_menu() {
  $items['my_module/ccallback' = array(
    // missing a menu item type (forgot the syntax)
    'callback function' => 'drupal_get_form',
    'callbsck arguments' => array('my_module_filters_form'),
    'access callback' => TRUE
  );
}

每次在HTML表单中进行更改时,都会对该回调执行ajax调用,并将HTML替换为您的输出。