J1.5

Adding a multiple item select list parameter type

From Joomla! Documentation

Revision as of 19:10, 28 November 2009 by Dziudek (talk | contribs) (Fixed problem with selecting more than one item)

The "J1.5" namespace is an archived namespace. This page contains information for a Joomla! version which is no longer supported. It exists only as a historical reference, it will not be improved and its content may be incomplete and/or contain broken links.

The standard list parameter type does not support selection of multiple items in Joomla 1.5.x. However, it is quite straightforward to add an additional custom parameter type with this functionality to any component or module. Note that this is not required for Joomla 1.6.x as that version supports multiple selection lists natively.

The code to support the custom parameter is in two parts. A single file containing all the code required to render the HTML SELECT list and a small piece of additional code to be added to whatever code processes the FORM after submission by the user. This could, for example, be the bind() method if the value(s) are being stored in a database table. In addition, you will want to add one or more <param> elements to the XML file which defines the form where the SELECT list is to be added.

Rendering the parameter[edit]

The code required to render the multiple item select list is here:

<?php
/**
* @copyright	Copyright (C) 2009 Open Source Matters. All rights reserved.
* @license	GNU/GPL
*/

// Check to ensure this file is within the rest of the framework
defined('JPATH_BASE') or die();

/**
 * Renders a multiple item select element
 *
 */

class JElementMultiList extends JElement
{
	/**
	* Element name
	*
	* @access	protected
	* @var		string
	*/
	var	$_name = 'MultiList';

	function fetchElement($name, $value, &$node, $control_name)
	{
		// Base name of the HTML control.
		$ctrl	= $control_name .'['. $name .']';

		// Construct an array of the HTML OPTION statements.
		$options = array ();
		foreach ($node->children() as $option)
		{
			$val	= $option->attributes('value');
			$text	= $option->data();
			$options[] = JHTML::_('select.option', $val, JText::_($text));
		}

		// Construct the various argument calls that are supported.
		$attribs	= ' ';
		if ($v = $node->attributes( 'size' )) {
			$attribs	.= 'size="'.$v.'"';
		}
		if ($v = $node->attributes( 'class' )) {
			$attribs	.= 'class="'.$v.'"';
		} else {
			$attribs	.= 'class="inputbox"';
		}
		if ($m = $node->attributes( 'multiple' ))
		{
			$attribs	.= ' multiple="multiple"';
			$ctrl		.= '[]';
		}

		// Render the HTML SELECT list.
		return JHTML::_('select.genericlist', $options, $ctrl, $attribs, 'value', 'text', $value, $control_name.$name );
	}
}

This should be saved in a file called multilist.php in a separate directory within your component or module directory. It is recommended that for consistency this directory is called elements, but this is not required. For example, if you want to add support for this field into a component called mycomponent, then you would copy-paste the above code into this file:

/administrator/components/com_mycomponent/elements/multilist.php

Don't forget to add an empty index.html file into the elements directory to prevent directory listing.

Adding the element to a form[edit]

Parameters are rendered using form definition information contained in an XML file. For example, for a component this file will typically be:

/administrator/components/com_mycomponent/config.xml

In this file, you should add one or more selection list parameters by adding a <param> element into an appropriate <params> parameter group, like this:

<param name="field-name" type="multilist" default="OPT1" multiple="multiple" label="Select one or more items"
 description="Select one or more items from the list.  You can use Ctrl-click to select more than one item.">
	<option value="OPT1">Title for option 1</option>
	<option value="OPT2">Title for option 2</option>
	<option value="OPT3">Title for option 3</option>
	<option value="OPT4">Title for option 4</option>
	<option value="OPT5">Title for option 5</option>
</param>

The arguments are as follows:

  • type (mandatory) must be multilist.
  • name (mandatory) is the unique name of the parameter.
  • label (mandatory) (translatable) is the descriptive title of the field.
  • default (optional) is a comma-separated list of default values.
  • size (optional) is the number of option rows that will be visible in the list. If omitted, all rows will be displayed.
  • description (optional) (translatable) is text that will be shown as a tooltip when the user moves the mouse over the drop-down box.
  • class (optional) is a CSS class name for the HTML form field. If omitted this will default to 'inputbox'.
  • multiple (optional) indicates whether the field will allow more than one option row to be selected. The should always be set to "multiple" since if it isn't you might as well use the standard list parameter type.

The XML <param> element must include one or more <option> elements which define the list items. The text between the <option> and </option> tags is what will be shown in the option list and is a translatable string. The <option> tag takes the following argument:

  • value (mandatory) is the value that will be saved for the parameter if this item is selected.

Since this is a custom parameter type, you will also need to tell Joomla where to find the code to render the parameter. You do this by adding an addPath argument to the containing <params> element. For example, to add a parameter group containing just a single multiple element selection list to your component, the XML would look like this:

<params group="group-name" addPath="/administrator/components/com_mycomponent/elements">

	<param name="field-name" type="multilist" default="OPT1" multiple="multiple" label="Select one or more items"
 description="Select one or more items from the list.  You can use Ctrl-click to select more than one item.">
		<option value="OPT1">Title for option 1</option>
		<option value="OPT2">Title for option 2</option>
		<option value="OPT3">Title for option 3</option>
		<option value="OPT4">Title for option 4</option>
		<option value="OPT5">Title for option 5</option>
	</param>
</params>

Only a single addPath argument is permitted per parameter group which is why it's a good idea to gather all your custom parameter code into a single elements directory.

Saving parameter values to a database[edit]

The most common use for this custom parameter type will involve saving whatever values the user selected into a field in a database table. Assuming you are doing this using the JTable API class, then you will need to add the following code to the JTable extended class for the appropriate table.

    /**
     * Overloaded bind function
     *
     * @param array $array  Array or object of values to bind
     * @param mixed $ignore Array or space separated list of fields not to bind
     *
     * @return null|string Success returns null, failure returns an error
     * @access public
     * @see    JTable:bind
     */
    function bind( $array, $ignore = '' )
    {
        if (key_exists( 'field-name', $array ) && is_array( $array['field-name'] )) {
	        $array['field-name'] = implode( ',', $array['field-name'] );
        }

        return parent::bind( $array, $ignore );
    }

Note that field-name must match the name you gave the field in the XML form definition file and the name given to the database field.

Using this code the data will be stored as a comma-separated list of values in the database field. To use a different separator, change the comma to whatever character you want to use in the implode function call in the bind() method and the corresponding explode function call in the multilist.php file.

See also[edit]