This article aims to show how to generate and implement selects in Magento based on the Mage_Core_Block_Html_Select class.

Dropdown selects – what are they?

The basic HTML components of a basic dropdown are <select>, <optgroup> and <option> tags. The typical markup of this element looks as follows:

<select name="animals">
	<option value="dog">Dog</option>
	<option value="cat">Cat</option>
</select>

This will nest the options list in one element, creating an expandable list. You can find more information about the tag here: http://www.w3schools.com/tags/tag_select.asp

Reinventing the wheel?

Often I had to create frontend selects fetching the data from a dynamic environment. Each time I wrote my own code from scratch or used the code written for one of the previous projects. It seems that it has always been a waste of time that could have been invested in things bringing more glory than a trivial select. One day I came across a code snippet for selects implementation that used classes included in the Magento core. I realized that I have been repeatedly reinventing the wheel: the framework I have worked with included everything I needed.

The Mage_Core_Block_Html_Select class

Magento has a simple tool generating selects when a script is run for dynamic implementation. The tool is available as a Mage_Core_Block_Html_Select class (/app/code/core/Mage/Core/Block/Html/Select.php). We recommend having a look at the file before continuing reading just to get a brief idea of the code.

The class interface consists of several methods. To make it easier, I will skip their implementation.

1. Methods related to options:

/** 
 * Get options of the element 
 * @return array 
 */ 
public function getOptions()
/** 
 * Set options for the HTML select 
 * @param array $options 
 * @return Mage_Core_Block_Html_Select 
 */ 
public function setOptions($options)
/** 
 * Add an option to HTML select 
 * @param string $value  HTML value 
 * @param string $label  HTML label 
 * @param array  $params HTML attributes 
 * @return Mage_Core_Block_Html_Select 
 */ 
public function addOption($value, $label, $params=array())

These methods are pretty easy and allow for full manipulation of the selects’ content. Soon we will have a closer look at one of them, namely setOptions(), because it gives you more powers that it can be expected from its prototype.

2. Methods related to attributes:

/**
 * Set element's HTML ID
 *
 * @param string $id ID
 * @return Mage_Core_Block_Html_Select
 */
public function setId($id)
/**
 * Set element's CSS class
 *
 * @param string $class Class
 * @return Mage_Core_Block_Html_Select
 */
public function setClass($class)
/**
 * Set element's HTML title
 *
 * @param string $title Title
 * @return Mage_Core_Block_Html_Select
 */
public function setTitle($title)
/**
 * HTML ID of the element
 *
 * @return string
 */
public function getId()
/**
 * CSS class of the element
 *
 * @return string
 */
public function getClass()
/**
 * Returns HTML title of the element
 *
 * @return string
 */
public function getTitle()

And this is basically everything in terms of the methods related to filling the class with data. Thanks to the setters we can sufficiently define any select, and the getters give access to the formerly defined attributes.

The first select

Now that we know the basics, let’s try a sample implementation of a typical select. We can use a magic array for that. It is magic because it is simply given to us. Here it is:

$animals = array(
  array(
    'value' => 'cat',
    'label' => 'Cat',
  ),
  array(
    'value' => 'dog',
    'label' => 'Dog',
  ),
  array(
   'value' => 'X',
   'label' => 'mother-in-law'
  ),
);

As you can see, we are dealing with a two-dimensional array. It will serve as a model for our select’s options.

Let’s call the Mage_Core_Block_Html_Select class. There are adequate blocks for the .phtml files, therefore, we can write the following line in any template file (all template files have .phtml extension):

$select = $this->getLayout()->createBlock('core/html_select');

Now, we can add the previously defined options:

$select->setOptions($animals);

and define the primary parameters:

$select->setName('animals')
->setClass('animals-select')
->setId('animals-select');

We could actually stop at this point, but I would also like to present the option which either will be used as the default value or or which should be selected for some reason, for example upon receiving information from the database.

The Mage_Core_Block_Html_Select extends the Mage_Core_Block_Abstract class which in turn extends Varien_Object. The last one contains the magic methods including __call() defining the overload for getters and setters. This allows for setting attributes in the following way: [$object]->set[$name]

Let’s set a default value for our object:

$select->setValue('X');

We can also set the default values collection transmitting the array to a parameter:

$select->setValue(
  array( 'X', 'dog' )
);

We know that the name ‘value’ should be used for the attribute because we can deduce it from some excerpts of the method that implements generating HTML for a select. The generator checks the value of a processed option and verifies if it is in the array of the chosen values.

Therefore, we created an object storing all information about our select. Now we need to reprocess the data and generate HTML code based on it. The following method can be used: Mage_Core_Block_Html_Select::getHtml(). The method is an alias for Mage_Core_Block_Html_Select::_getHtml() which is protected, so we do not have direct access to it.

Let’s now generate the select’s code:

echo $select->getHtml();

The ‘echo’ command is essential as the getHtml() method returns a chain.

With the small effort we received a standard (but excellent!) select. It might not be very spectacular, but it definitely saves you a lot of time. Bearing in mind that the options array can be taken from any source and its data can be a composition of information processed when the program is run, it turns out that we have found a quick and useful tool for processing the data without writing too much boring code. All this will definitely improve our work efficiency.

However, the class in question provides us with more possibilities. If you want to extend your select by options groups, it can be done very easily. Let’s look into it using our magic array in a new form. Here it is:

$animals = array(
  array(
    'label' => 'Wild Animals',
    'value' =>
      array (
        'label' => 'Cat',
        'value' => 'cat',
      ),
      array (
        'label' => 'Lion',
        'value' => 'lion',
      ),
  ),
);

We just have to create a multilevel array. If the value is a array, the generator will process the information and create a group with the name identical to the chain assigned to the key called ‘label’.

Next, we will use the already known method:

echo $select->setOptions($animals)->getHtml();

And voila!

The data that the select options are based on can be stored in a simpler form of associative array. Instead of transferring subsequent arrays as index values, we can simply transfer the $value => $label pair:

$animals = array(
  array(
    'value' => 'cat',
    'label' => 'Cat',
  ),
  array(
    'value' => 'dog',
    'label' => 'Dog',
  ),
  array(
    'value' => 'X',
    'label' => 'mother-in-law'
  ),
);

We can also write it as follows:

$animals = array(
  'cat' => 'Cat',
  'dog' => 'Dog'
  (...),
);

Looks nicer, doesn’t it?

Now you know everything that is essential for the proficient use of the Mage_Core_Block_Html_Select class and generating selects anywhere in your templates based on any data processed into an array.