Drupal自动完成,具有多个参数的回调

时间:2011-07-21 13:16:02

标签: drupal autocomplete callback drupal-7

我在表单上添加了一些自动完成功能。问题是在回调中,只有文本字段中的字符串可以使用自动完成功能。我还想从回调中的另一个文本字段中访问一个值。这怎么可能?

/**
 * Implements hook_form_alter().
 */
function webform_conversion_jquery_form_webform_client_form_1_alter(&$form, &$form_state, $form_id) {
          //Load some extra function to process data
        module_load_include('inc', 'webform_conversion_jquery', '/includes/dataqueries');

        //Add extra js files
        drupal_add_js(drupal_get_path('module', 'webform_conversion_jquery') . '/js/conversionform.js');
        $form['submitted']['correspondentadress']['cor_street']['#autocomplete_path'] = 'conversionform/conversion_street';
    }
}

/**
 * Implements hook_menu().
 */
function webform_conversion_jquery_menu() {
    $items = array();


    $items['conversionform/conversion_street'] = array(
        'title' => 'Conversion street autocomplete',
        'page callback' => 'conversion_street_autocomplete',
        'access callback' => 'user_access',
        'access arguments' => array('access content'),
        'type' => MENU_CALLBACK,
    );

    return $items;
}

/**
 * Retrieve a JSON object containing autocomplete suggestions for streets depending on the zipcode.
 */
function conversion_street_autocomplete($street = '') {
    $street = "%" . $street . "%";
    $matches = array();
    $result = db_select('conversion_adresslist')
                    ->fields('conversion_adresslist', array('street'))
                    ->condition('street', $street, 'like')
                    ->execute();
    foreach ($result as $street) {
        $matches[$street->street] = $street->street;
    }
    drupal_json_output($matches);
}

我只是希望能够在函数中发布额外信息:

conversion_street_autocomplete($street = '', $extraparameter)

4 个答案:

答案 0 :(得分:2)

我遇到了同样的问题,并找到了一种不太费劲的方法。它涉及覆盖文本域主题,然后将参数传递给主题函数。

首先创建声明你的主题函数:

function mymodule_theme() {
  $theme_hooks = array(
    'my_module_autocomplete' => array(
      'render element' => 'element',
    ),
  );
  return $theme_hooks;
}

接下来,我们需要将主题和变量添加到表单元素中。在我的例子中,表单元素是字段小部件的一部分:

 function my_module_field_widget_form($form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {

  if($instance['widget']['type'] == 'my_module_field_type') {

    $element['my_module_field'] = array(
      '#type' => 'textfield',
      '#autocomplete_path' => 'my-module/autocomplete',
      // THIS IS THE IMPORTANT PART - ADD THE THEME AND THE VARIABLE.
      '#theme' => 'my_module_autocomplete',
      '#my_module_variable' => $field['field_name'],
    );
  }
  return $element;
}

然后实现主题功能。这是来自theme_textfield的{​​{1}}的副本,但有一个重要区别 - 我们将变量附加到自动完成路径:

includes/form.inc

现在变量将作为自动完成回调函数的第一个参数:

function theme_my_module_autocomplet($variables) {
  $element = $variables['element'];
  $element['#attributes']['type'] = 'text';
  element_set_attributes($element, array('id', 'name', 'value', 'size', 'maxlength'));
  _form_set_class($element, array('form-text'));

  $extra = '';
  if ($element['#autocomplete_path'] &&     drupal_valid_path($element['#autocomplete_path'])) {
    drupal_add_library('system', 'drupal.autocomplete');
    $element['#attributes']['class'][] = 'form-autocomplete';

    $attributes = array();
    $attributes['type'] = 'hidden';
    $attributes['id'] = $element['#attributes']['id'] . '-autocomplete';
    // THIS IS THE IMPORTANT PART. APPEND YOUR VARIABLE TO THE AUTOCOMPLETE PATH.
    $attributes['value'] = url($element['#autocomplete_path'] . '/' . $element['#my_module_variable'], array('absolute' => TRUE));
    $attributes['disabled'] = 'disabled';
    $attributes['class'][] = 'autocomplete';
    $extra = '<input' . drupal_attributes($attributes) . ' />';
  }

  $output = '<input' . drupal_attributes($element['#attributes']) . ' />';

  return $output . $extra;
}

答案 1 :(得分:0)

您可以通过在自己的js中覆盖autocomplete.js中的方法来实现。这是一个例子:

(function($) {
  Drupal.behaviors.someModuleOverrideAC = {
    attach: function(context, settings) {
      // Next is copied and adjusted method from autocomplete.js
      Drupal.jsAC.prototype.populatePopup = function() {
        var $input = $(this.input);
        var position = $input.position();
        // Show popup.
        if (this.popup) {
          $(this.popup).remove();
        }
        this.selected = false;
        this.popup = $('<div id="autocomplete"></div>')[0];
        this.popup.owner = this;
        $(this.popup).css({
          top: parseInt(position.top + this.input.offsetHeight, 10) + 'px',
          left: parseInt(position.left, 10) + 'px',
          width: $input.innerWidth() + 'px',
          display: 'none'
        });
        $input.before(this.popup);

        // Do search.
        this.db.owner = this;

        if ($input.attr('name') === 'field_appartment_complex') {
          // Overriden search
          // Build custom search string for apartments autocomplete
          var $wrapper = $('div.apartments-autocomplete');
          var $elements = $('input, select', $wrapper);
          var searchElements = {string: this.input.value};
          $elements.each(function() {
            searchElements[$(this).data('address-part')] = $(this).val();
          });
          var string = encodeURIComponent(JSON.stringify(searchElements));
          this.db.search(string);
        }
        else {
          // Default search
          this.db.search(this.input.value);
        }
      };
    }
  };
}(jQuery));

在您的服务器回调中:

function some_module_autocomplete_ajax($string) {
  // Decode custom string obtained using overriden autocomplete js.
  $components = drupal_json_decode(rawurldecode($string));
  // Do you search here using multiple params from $components
}

答案 2 :(得分:0)

万一有人仍然遇到这个问题我找到了一个很好的解决方案,同时试图找出如何做到这一点。我有一年选择列表,并且指示了自动填充字段中显示的数据。该解决方案基本上具有选择列表的ajax回调函数,然后可以使用url中的额外参数更新自动完成字段。无论如何,在下面的文章中对它进行了很好的解释。

http://complexdan.com/passing-custom-arguments-drupal-7-autocomplete/

*请注意,我疯狂地试图弄清楚它为什么不起作用,事实证明你不能在页面上使用相同的表格两次(我需要因为我以不同方式显示它)对于移动设备),因为您使用id作为ajax回调。为此我添加了一个额外的参数。在下面的例子中它被称为uniqueid。

function report_cards_comparison_form($form, &$form_state, $uniqueid) {

   $curryear = t('2012');

   $form['year_select'] = array(
        '#title' => t('School Year'),
        '#type' => 'select',
        '#options' => array(
            '2012' => t('2012'),
            '2013' => t('2013'),
            '2014' => t('2014'),
            '2015' => t('2015'),
          ),
        '#default_value' => $curryear,
        '#ajax' => array(
          'callback' => 'report_cards_comparison_form_callback',
          'wrapper' => $uniqueid,
          'progress' => array(
                'message' => 'Updating Schools...',
                'type' => 'throbber'
            ),
        ),

  ); 

  $form['choice'] = array(
    //'#title' => t('Search By:  School Name'),
    '#type' => 'textfield',
    '#attributes' => array(
        'class' => array('school-choice'),
        'placeholder' => t('Start Typing School Name...'),
    ),
    '#required' => TRUE,
    '#autocomplete_path' => 'reportcards/autocomplete/' . $curryear,
    '#prefix' => '<div id="' . $uniqueid . '">',
    '#suffix' => '</div>',
  ); 

  $form['submit'] = array(
    '#type' => 'submit',
    '#prefix' => '<div class="submit-btn-wrap">',
    '#suffix' => '</div>',
    '#value' => t('Search'),
    '#attributes' => array('id' => 'add-school-submit'),
  );

  return $form;
}

/**
 * Ajax Callback that updates the autocomplete ajax when there is a change in the Year Select List
 */
function report_cards_comparison_form_callback($form, &$form_state) {
  unset($form_state['input']['choice'], $form_state['values']['choice']);
  $curryear = $form_state['values']['year_select'];

  $form_state['input']['choice'] = '';
  $form['choice']['#value'] = '';
  $form['choice']['#autocomplete_path'] = 'reportcards/autocomplete/' . $curryear;

  return form_builder($form['#id'], $form['choice'], $form_state);
}

我可以通过这样做来调用表单......

print render(drupal_get_form('report_cards_comparison_form', 'desktop-schoolmatches'));

答案 3 :(得分:-1)

好的,就我所知,这是不可能的。也许你可以使用fapi http://api.drupal.org/api/drupal/developer--topics--forms_api_reference.html/7#ajax

中的ajax功能推出自己的功能

现在我通过实现drupal 7中包含的jquery.ui.autocomplete来解决它