Автозаполнение Drupal, обратный вызов с несколькими параметрами - PullRequest
2 голосов
/ 21 июля 2011

Я добавляю автозаполнение в форму. Проблема в том, что в обратном вызове доступна только строка в текстовом поле. Автозаполнение включено, доступно. Я также хочу получить доступ к значению из другого текстового поля в обратном вызове. Как это возможно?

/**
 * 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 ]

2 голосов
/ 18 февраля 2014

У меня была такая же проблема, и я нашел способ, который не слишком напряженный. Это включает переопределение темы текстового поля и затем передачу вашего параметра в функцию темы.

Сначала создайте объявите функцию вашей темы:

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 из 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;
}

Теперь переменная будет доступна в качестве первого параметра функции обратного вызова автозаполнения:

function _my_module_autocomplete($my_module_variable, $search_string) {
  // Happy days, we now have access to our parameter.
}
0 голосов
/ 16 мая 2014

На всякий случай, если у кого-то все еще есть проблемы с этим, я нашел отличное решение, пытаясь выяснить, как это сделать.У меня был список выбора года, и он определял, какие данные должны отображаться в поле автозаполнения.Решение в основном имеет функцию обратного вызова ajax для списка выбора, которая может затем обновить поле автозаполнения дополнительным параметром в URL.В любом случае, это действительно хорошо объяснено в следующей статье.

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

* Внимание, я сходил с ума, пытаясь понять, почему это не сработало, и оказалось, чтоВы не можете иметь одну и ту же форму на странице дважды (мне это нужно, потому что я отображал ее по-разному для мобильных устройств), потому что вы используете идентификатор для обратного вызова 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'));
0 голосов
/ 06 декабря 2013

Вы можете сделать это, переопределив методы из autocomplete.js в вашем собственном 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
}
0 голосов
/ 25 июля 2011

Хорошо, насколько я понимаю, это невозможно. может быть, вы можете свернуть свой собственный с функциональностью ajax в fapi http://api.drupal.org/api/drupal/developer--topics--forms_api_reference.html/7#ajax

Пока что я решил эту проблему, реализовав jquery.ui.autocomplete, который включен в drupal 7

...