One of our clients manages a Masters program and has a list of participating schools from around the globe. Because the program is similar at each institution, but has different admission and tuition requirements, the client wanted us to develop a tool for prospective students to easily compare each school. Students select their prospective schools, and the tool shows them all the necessary information in a table format.
Sounds easy enough with Views, right? Unfortunately, there’s no “out of the box” method of filtering a View by a list of school nodes. You can filter by “Node: Title” but that’s just a text box. We need to do something different. We need to create a Views style plugin and use a bit of creativity.
After some research and discussion with the CivicActions crew (by the way, if you don’t have a group of knowledgeable Drupal developers you can constantly bug with technical theories, you’re missing out!) I have my plan of attack:
- Create a View with a Page display to show the schools and their information in a table.
- Create a Block display that would list the school nodes as a list of checkboxes.
- Display the block on the View page, above the list of schools.
- Set the View to use the school nids as an argument, so when they’re checked and updated, the table display updates.
It took a few extra tricks to get everything working, but the process is fairly straightforward. Here’s how it’s done.
(Note: this is all being done in Drupal 6 with Views 2. The theories should apply to Drupal 7 and Views 3, but the code will probably need to be changed.)
Creating Our Table And Swapping Columns And Rows
Creating the page View was basic enough: create a Page variant, add the fields, a few filters to specify our published node type, and use the Table style plugin. However, by default this plugin will display the fields as the columns, and the nodes as rows. We don’t want this, since it makes more sense to have the schools listed at the top, so students could browse the details list horizontally.
A few minutes of Googling turned up this handy post about how to swap the rows and columns in a Views display. All it takes is a new tpl file in your theme. Copy the code into a file called views-view-table.tpl.php in your theme directory, clear your Drupal caches, and voila, the rows and columns are swapped.
Of course, this means that every table View will be swapped. If you want to just have this happen for one particular View (which we do) you’ll need to rename the template file to be more specific. This is easy, by following the pattern:
Note the double-dash before view name. In our case, the View is called “program_comparison”, so our template file becomes:
Here’s more details on Views theming.
Configuring The Checkbox Block Variant
We want to filter our table View by a list of nodes, which isn’t possible with the default Views filter settings. Instead, we create a new View variant as a block that will display a list of nodes as checkboxes, and use that to filter our view.
The first step is to modify our original Page variant to include an Argument of Node: Nid. This allows us to filter based on the selected nodes. We configure our View to Display all values if no argument is present, and Allow multiple terms per argument so we can select multiple schools.
Next, we create a Block variant that lists our published school nodes, and includes two fields, Node: Title and Node: Nid. For the Node: Nid field, make sure to select Exclude from display as we’ll only be using this value to pass an argument. You’ll also want to remove the label from the node title, so only the node names appear next to the checkboxes.
Now we want to display our block on the View page, but nowhere else. Using either Blocks or Context, configure the block to only appear in the path relating to your View, in a region above the main content, e.g. Content Top.
Creating The Checkbox Views Plugin
The final step is creating a Views Style Plugin that will display our block of school nodes as checkboxes, and allow us to filter by them. Creating a Views plugin is, like many things in Drupal, a simple process when you know what you’re doing, but can be intimidating if you don’t know where to start. Here’s how it works, following the instructions from this great post.
First, you’ll need a custom module to put our code and store our Views configuration files. Let’s say ours is called “compare”. In compare.module, we need to implement hook_views_api() so that Views knows to look at our code for changes.
* Implementation of hook_views_api().
This is a CRITICAL STEP. If you don’t include this hook, none of the following code will work, and it will fail silently while you to slam your head on the desk repeatedly in frustration.
Next, we need to create a new file to store our plugin definition. Views looks for a file called module_name.views.inc, so we create a file called comparison.views.inc in the same directory as comparison.module (you can also put this file in an “includes” sub-directory). In this file, we declare our new checkbox plugin:
* Implementation of hook_views_plugins().
Most of these array variables should seem obvious, but the key one is handler which designates a name for our actual plugin code. This is both the name of our plugin code filename, and the PHP class we’re creating that configures the plugin (read this post for more general information on Views plugins).
Now we create our plugin file. Create another file in your module directory called views_plugin_style_checkbox_list.inc and include the following code (which was adapted from the Jump Menu plugin found in plugins/views_plugin_style_jump_menu.inc in the Views directory):
* Style plugin to render each item as a list of checkboxes, for filtering.
* @ingroup views_style_plugins
class views_plugin_style_checkbox_list extends views_plugin_style
* Render the given style.
function options_form(&$form, &$form_state)
‘#value’ => t(‘To properly configure the checkboxes, you must select one field that will represent the path to utilize. You should then set that field to exclude. All other displayed fields will be part of the menu.’),
‘#prefix’ => ‘
‘#suffix’ => ‘
foreach ($handlers as $id => $handler)
$form[‘path’] = array(
‘#type’ => ‘select’,
‘#title’ => t(‘Path field’),
‘#options’ => $options,
‘#default_value’ => $this->options[‘path’],
$form[‘text’] = array(
‘#type’ => ‘textfield’,
‘#title’ => t(‘Button text’),
‘#default_value’ => $this->options[‘text’],
* Render the display in this style.
* This is overridden so that we can render our grouping specially.
$grouping = url($grouping);
$sets[$grouping] = $row;
// Turn this all into an $options array for the jump menu.
$this->view->row_index = 0;
$options = array();
foreach ($sets as $title => $records)
$settings = array(
‘hide’ => $this->options[‘hide’],
‘button’ => $this->options[‘text’],
return drupal_get_form(‘comparison_views_checkbox_list_form’, $options, $settings);
function render_set($title, $records)
Next, we need a theme function to display the nodes as a list of checkboxes. We use Drupal’s Form API for this, with some custom code that takes the Nid arguments and properly parses them as URL arguments. It also sets them as default arguments, so they stayed checked when the page refreshes:
function comparison_views_checkbox_list_form($form_state, $options, $settings = array())
Now we write a custom submit handler that redirects back to our View page, with the Nid arguments in the URL:
function comparison_views_checkbox_list_form_submit($form_id, $form_state)
drupal_goto(‘program-comparison/’ . join(“,”, $ids));
Now that we’ve finished creating the View style plugin, we go back to our Block variant (after clearing all Drupal caches, as these View settings are cached) and we should have a new option Checkbox list under the View Style setting. Select this option, configure if you need to, and we’re done!