You are here

Drupal 7 - A Simple Content Type: Using the Select Widget

This post builds upon a previous post: Drupal 7 - A Simple Content Type

The next widget type we'll use with our Simple Content Type is the 'options_select' widget, probably better known in HTML worlds as a select drop down list. This widget is implemented by the List module in the hook list_field_info().The List module is also responsible for implementing the 'options_buttons' widget we used to create the checkboxes and radio buttons of another example. Continuing on the theme of previous examples we are going to use the Field API to set-up and define the way our new Simple Content Type should behave. This example will only have a title and a (static at first) select widget. Here is the updated hook_install() function:


function simple_content_type_install() {
/**
 * Implements hook_install().
 * - Add a title
 * - Add a select list
 */
function simple_content_type_install() {
  // create the simple content type
  node_types_rebuild();
  $types = node_type_get_types();
  
  // create all the fields we are adding to our content type
  foreach (_simple_content_type_installed_fields() as $field) {
    field_create_field($field);
  }
  
  // create all the instance for our fields
  foreach (_simple_content_type_installed_instances() as $instance) {
    $instance['entity_type'] = 'node';
    $instance['bundle'] = 'simple_content_type';
    field_create_instance($instance);
  }
  
  // disable comments for this content type
  variable_set('comment_simple_content_type', COMMENT_NODE_CLOSED);
}

We use two foreach statements coupled with functions that return associative arrays to make the task of adding fields to our content type easy. We could just stuff the settings into the install function seeing as we only have one field to add and configure but this makes the code more readable. We next need to modify the uninstall hook to delete any fields we created for our content type. Here is our updated hook_uninstall() function:


/**
 * Implements hook_uninstall().
 */
function simple_content_type_uninstall() {
  // gather all the content while the module was enabled
  $result = db_select('node', 'n')
    ->fields('n', array('nid'))
    ->condition("n.type", 'simple_content_type')
    ->execute();
  
  $nids = array();
  foreach ($result as $row) {
    $nids[] = $row->nid;
  }
  
  // delete all the nodes at once
  node_delete_multiple($nids);

  // delete all the fields defined by this module
  foreach (array_keys(_simple_content_type_installed_fields()) as $field) {
    field_delete_field($field);
  }

  // delete any remaining field instances attached to this content type
  $instances = field_info_instances('node', 'simple_content_type');
  foreach ($instances as $instance_name => $instance) {
    field_delete_instance($instance);
  }
  
  // delete our content type
  node_type_delete('simple_content_type');
  
  // purge all field information
  field_purge_batch(1000);
  
  // delete any variables we set
  variable_del('comment_simple_content_type');
}

Both of the functions we are using in the above hooks reside in a new file called 'simple_content_type_functions.inc'. This file holds all the non-hook functions we code for use in our hooks. In order to use the functions in this file we need to add the new functions file to the .install and .module files:


require_once('simple_content_type_functions.inc');

Without adding this file include to the module.module file, even though it is not directly referenced there, our content type will not be able to find the function we set-up to populate the array holding our options list. The new file, simple_content_type_functions.inc, has three functions used to help define the behavior in our content type:


/**
 * Associative array of fields to add to our content type
 */
function _simple_content_type_installed_fields()  {
  $fields['simple_content_type_select'] = array(
    'field_name' => 'simple_content_type_select',
    'label' => t('Select an option from the list'),
    'type' => 'list_integer',
    'cardinality' => '1', // change this to -1 to enable ctrl+select
    'foreign keys' => array(),
    'indexes' => array(
      'value' => array(
        0 => 'value',
      ),
    ),
    'module' => 'list',
    'settings' => array(
      'allowed_values_function' => '_simple_content_type_options_list',
    ),
  );
  
  return $fields;
}
/**
 * Associative array of instance settings for our fields
 */
function _simple_content_type_installed_instances()  {
  // select widget
  $instances['simple_content_type_select'] = array(
    'field_name' => 'simple_content_type_select',
    'label' => t('You Selected'),
    'description' => t('Select an option from the list.'),
    'default_value' => NULL,	// add a default value here that matches your key => index values
    'display' => array(
      'default' => array(
        'label' => 'above',
        'module' => 'list',
        'settings' => array(),
        'type' => 'list_default',
        'weight' => -1,
      ),
      'teaser' => array(
        'label' => 'above',
        'settings' => array(),
        'type' => 'hidden',
        'weight' => -1,
      ),
    ),
    'required' => 1,
    'settings' => array(
      'user_register_form' => FALSE,
    ),
    'widget' => array(
      'active' => 1,
      'module' => 'options',
      'settings' => array(),
      'type' => 'options_select',
      'weight' => '-1',
    ),
  );
  
  return $instances;
}
/**
 * Options callback for simple_content_type_checkboxes field
 * @return - returns an indexed array as integer => string
 */
function _simple_content_type_options_list()  {
  $options = array(
    1 => 'Option A',
    2 => 'Option 2',
    3 => 'Option C',
    4 => 'Option 4',
    5 => 'Option E',
    6 => 'Option 6',
  );
  return $options;
}

We are setting our select list field 'type' as a list of integers which allows us to create key => value pairs like you see in the '_simple_content_type_options_list()' function using an integer as the key in the pair. We could also use the 'list_text' type if we wanted to use strings as the keys in our pairs. The fields settings help to determine whether our field will be "Ctrl+select"-able or not; by setting the 'cardinality' to '1' we tell Drupal that our field only accepts one single value and it should not allow the user to select more than one value, setting it to '-1' tells Drupal that the user can select multiple options and so should hold the "Ctrl" key at the same time as they select options to submit multiple values. Our instances function sets the widget, display, and a host of other settings which affect how our field will be displayed to the user. I won't delve too much into the Field UI here, we'll save that for another time. Lastly, the function we set up to populate our options list creates an associative array and returns it when called.

Simple Content Type data table

To make our select list options dynamic, we change the _simple_content_type_options_list() in our functions file:


/**
 * Options callback for simple_content_type_checkboxes field
 * @return - returns an indexed array as integer => string
 */
function _simple_content_type_options_list()  {
  // use this method to populate the demo list from the list of courses
  $vocab = taxonomy_vocabulary_machine_name_load('andy_pangus');
  $vid = $vocab->vid;
  $results = db_select('taxonomy_term_data', 't')
    ->fields('t', array('tid', 'name'))
    ->condition("t.vid", $vid)
    ->execute();
  
  $options = array();
  foreach ($results as $term)  {
    $options[$term->tid] = $term->name;
  }
  return $options;
}

The updated function creates an associative array from a list of vocabulary terms which could contain few or many terms that could be added or deleted at any time. I have created a helper module called Simple Vocab to provide a set of terms for us to use in the dynamic example. The simple_vocab module contains code that creates a vocabulary, machine name: andy_pangus, and adds some terms to it. This module is required for the dynamic example to work and is included in the download below. Just for fun the dynamic example also enables multiple values for the select widget:

Simple Content Type data table

Download the source for the static example.

Download the source for the dynamic example.

Tags: 

wow really good article

At last, I found your article which explains very well how to build the options_select widget in a Drupal 7 field.
Thanks. You saved my day!

This was exactly what I was looking for. You saved me some time, thank you.

Post new comment

Filtered HTML

  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <blockquote> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
By submitting this form, you accept the Mollom privacy policy.