1

I'm trying to create a custom module for Drupal 7 that makes two widgets available for Text fields. The widgets are showing up in the list of available widgets, but when I select one of them as the widget for a Text field, the field isn't visible on the form (although it is still listed in the Manage Fields section and its settings can be changed as normal). Here's my code so far:

<?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) {
    //load the default text instance
    $element += text_field_widget_form($form, $form_state, $field, $instance, $langcode, $items, $delta, $element);

    /*if ($instance['widget']['type'] == 'autocomplete_speaker_name') {
        $element['value']['#autocomplete_path' ] = 'jsbu/speaker/autocomplete';
    } else if($instance['widget']['type'] == 'autocomplete_venue_name') {
        $element['value']['#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');

    $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');

    $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 on what I'm doing wrong there/anything else I might need to add? Is the problem that I'm missing a hook?

EDIT: $element just before return:

Array (
    [#entity_type] => node
    [#bundle] => event
    [#field_name] => field_event_speaker
    [#language] => und
    [#field_parents] => Array
        (
        )

    [#columns] => Array
        (
            [0] => value
            [1] => format
        )

    [#title] => Speaker
    [#description] => 
    [#required] => 
    [#delta] => 0
    [value] => Array
        (
            [#autocomplete_path] => jsbu/speaker/autocomplete
        )

)
2

I think it's because you're missing the type, however, to make things easier and more compatible, why not load the "stock" widget and make modifications?

Try adding this instead of your $element declarations:

$element += text_field_widget_form($form, $form_state, $field, $instance, $langcode, $items, $delta, $element);

That should load the default text form, then you can make modifications. You can take a look at the code it uses directly: see line 502 of text.module.

Your simplified code might look something like this:

   //load the default text instance
   $element += text_field_widget_form($form, $form_state, $field, $instance, $langcode, $items, $delta, $element);

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

   return $element;
  • Thanks for the response! Unfortunately, that didn't seem to work -- the field still isn't showing up. Maybe I need to use hook_field_widget_form_alter? – BenjaminRH Jan 24 '12 at 16:33
  • To clarify, my last code block should be the ONLY code in your function. Do you have devel installed? try adding kpm($element); before the return and refresh once or twice. What does the output of KMP (krumo) look like? Anything interesting? Comment out the "if statement"... still nothing? I mean, at that point you're just loading the default form. You should at least get the default text field... – Jonathan Rowny Jan 24 '12 at 16:39
  • I've added the element just before it's returned. But when I use the code you provided and comment out everything but first two lines there, it's still not showing up. – BenjaminRH Jan 24 '12 at 17:08
  • never mind -- I solved it by taking the code directly from the text.module link you provided. Thanks for the help! – BenjaminRH Jan 24 '12 at 17:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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