3

I'm trying to create a custom module for Drupal 7 that makes two widgets available for Text fields. They autocomplete from a database table using #autocomplete_path. The autocomplete works fine and when a match is selected it is made the value for the field, but when the node is saved only the first letter from that field is shown. Then when the node is edited, the field comes up blank in the edit form.

Here's my module code:

<?php
/**
 * Implements hook_menu().
 */
function autocomplete_jsb_users_menu() {
    $items['jsbu/speaker/autocomplete'] = array(
        'page callback' => 'jsbu_speaker_autocomplete',
        'access callback' => TRUE,
        'weight' => 1,
    );
    $items['jsbu/venue/autocomplete'] = array(
        'page callback' => 'jsbu_venue_autocomplete',
        'access callback' => TRUE,
        'weight' => 2,
    );
    return $items;
}

/**
 * Implements hook_field_widget_info().
 *
 * Two widgets are provided.
 * - A textfield Speaker name autocomplete widget.
 * - A textfield Venue name autocomplete widget.
 */
function autocomplete_jsb_users_field_widget_info() {
    return array(
        'autocomplete_speaker_name' => array(
            'label' => t('Autocomplete Speaker Name'),
            'field types' => array('text'),
        ),
        'autocomplete_venue_name' => array(
            'label' => t('Autocomplete Venue Name'),
            'field types' => array('text'),
        ),
    );
}

/**
 * Implements hook_field_widget_form().
 */
function autocomplete_jsb_users_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
    // set the default text instance
    $element += array(
        '#type' => 'textfield',
        '#size' => $instance['widget']['settings']['size'],
        '#maxlength' => $field['settings']['max_length'],
        '#attributes' => array('class' => array('text-full')),
    );

    if ($instance['widget']['type'] == 'autocomplete_speaker_name') {
        $element['#autocomplete_path' ] = 'jsbu/speaker/autocomplete';
    } else if($instance['widget']['type'] == 'autocomplete_venue_name') {
        $element['#autocomplete_path' ] = 'jsbu/venue/autocomplete';
    }

    return $element;
}

/**
 * Implements the autocomplete_jsbu_speaker() callback.
 */
function jsbu_speaker_autocomplete() {
    $matches = array();

    // Query the database
    $query = db_select('field_data_field_speaker_name', 'sn');

    // Select rows that match the string
    $query
        ->fields('sn', array('field_speaker_name_value'))
        ->orderBy('field_speaker_name_value', 'DESC')
        ->distinct();

    $result = $query->execute();

    // add matches to $matches  
    foreach ($result as $row) {
        $matches[$row->field_speaker_name_value] = check_plain($row->field_speaker_name_value);
    }

    // return for JS
    drupal_json_output($matches);
}

/**
 * Implements the autocomplete_jsbu_venue() callback.
 */
function jsbu_venue_autocomplete() {
    $matches = array();

    // Query the database
    $query = db_select('field_data_field_venue_name', 'vn');

    // Select rows that match the string
    $query
        ->fields('vn', array('field_venue_name_value'))
        ->orderBy('field_venue_name_value', 'DESC')
        ->distinct();

    $result = $query->execute();

    // add matches to $matches  
    foreach ($result as $row) {
        $matches[$row->field_venue_name_value] = check_plain($row->field_venue_name_value);
    }

    // return for JS
    drupal_json_output($matches);
}

Any ideas? Thanks!

1 Answer 1

3

It may help to just wrap the returned array from the _field_widget_form in yet another array

return array('anything' => $element);

Worked for me ;)

2
  • Thanks. That solved the problem that'd had me banging my head against the desk all morning.
    – drewish
    Aug 24, 2012 at 18:09
  • Well that and a cache clear ;)
    – drewish
    Aug 24, 2012 at 20:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.