Create an Exponent Module - Part 2
Ok, we have our basic module down and now we would like to have our module display the albums in different ways. Let’s use two examples in our article:
Example 1
Let’s say that we want to generate a list of all the albums, but in some sections of our website we want that data to display in one column, and in others we want a two column display. We will need showall_One Column.tpl and showall_Two Columns.tpl, respectively.
Example 2
Let’s say we want to have only the most recent album display on a page, and we want to have two options for how it displays. In showlatest_With Year.tpl, we want to see the latest album displayed with a picture of the album. In showlatest_Without Year.tpl, we want to see the album info displayed without a thumbnail.
Example 1 -- Implemented
The first thing we need to do is create two new TPL views in the folder framework/modules/ albums/views
I have created one that I call showall_One Column.tpl
Creating this file is important for two reasons:
- The action in the controller that is named showall will pass data to this view. This is because, in Exponent, actions pass off to views that are named starting with their action name. So, for example, if we have an action called showone that picks one album at random, then we could have multiple views for how to display that one album. Since the action is names showone, our views will have to start with showone . So, we could theoretically have the following views for the same function:
- showone_With_Pic.tpl
- showone_With_Video.tpl
- showone_With_Only_Text.tpl
In exponent, certain functions are autogenerated for each controller, and those functions can be seen in framework/core/controllers/expController.php
Some of the functions that our albumsController (and all other controllers) will have available to it without us having to write any code are:
- showall
- This will gather all of the items in your database and pass them to the view in an array called $items.
- show
- This will show a single item by its’ ID in the database or by the title passed to it. It will return the data to the view in an array called $record
- showByTitle
- This will search for an item by its’ title and then return that item to the view in a variable called $record
- showRandom
- This will return all items in a random order in an array called $items
- This can be limited by passing “limit” as a GET parameter with a number
- create, edit, update, delete
- all of your basic CRUD operations are provided by expController.
...just to name a few. There are more that we will cover in detail later. This means that we do not have to write any of these functions unless we want to override default behavior. If we want to override default behavior, we simply need to add a function of the same name to our albumsController.php and the system will use our function instead of the default.
In our case, we have a showall function already provided for us, so we do not have to write anything extra in our controller. Notice also that because of the first tutorial, we already have this line in our albumsController.php:
public $useractions = array('showall'=>'Show all');
The $useractions array in each controller tells the system which functions the user can access when adding the module to a page. Since the function is called showall we use that as the first parameter in the associative array and the second parameter is the string we want the user to see when selecting the action for this module, that is, it is what will show up in the dropdown for selecting an action, as seen here:
We will name it showall_One Column.tpl Later, we will want to create a two column view, so let’s go ahead and do that now. These views belong under framework/modules/albums/views/albums
This will become important later because when we go to put our module on a page, we will choose from actions and associated views. When we do that, because these two views start with showall we will see them as options when we choose the showall action.
Here we can see that in action: notice that the action selected is Show all and the views that show up are the ones we have created here.
We should now edit the TPL and see how it looks:
Paste the following code into your TPL:
<div class="module albums show-onecolumn"> {if $moduletitle}<h1>{$moduletitle}</h1>{/if} <div class="onecolumn-wrap"> {foreach name=items from=$items item=item} <div class="item"> <h2>{$item->title}</h2> {permissions level=$smarty.const.UILEVEL_NORMAL} <div class="actions"> {if $permissions.edit == 1} {icon controller=albums action=edit id=$item->id title="Edit this `$modelname`"} {/if} {if $permissions.delete == 1} {icon controller=albums action=delete id=$item->id title="Delete this `$modelname`" onclick="return confirm('Are you sure you want to delete this `$modelname`?');"} {/if} {if $permissions.edit == 1} {if $smarty.foreach.items.first == 0} {icon controller=albums action=`rank` img=up.png id=$item->id push=up} {/if} {if $smarty.foreach.items.last == 0} {icon controller=albums action=`rank` img=down.png id=$item->id push=down} {/if} {/if} </div><!-- end actions --> {/permissions} {if $item->artist !="" || $item->year !=""} <ul class="album-data"> {if $item->artist} <li> <h3 class="album-artist"> {$item->artist} </h3> </li> {/if} {if $item->year} <li> <h4 class="album-year"> {$item->year} </h4> </li> {/if} </ul> {/if} {if $item->body} <div class="bodycopy"> {$item->body} </div> {/if} {clear} </div><!-- end item --> {/foreach} </div><!-- end onecolumn-wrap --> {permissions level=$smarty.const.UILEVEL_NORMAL} {if $permissions.create == 1 || $permissions.edit == 1} {icon controller=albums class="add" action=create text="Create new album" title="Create a new album"} {/if} {/permissions} </div><!-- end show-onecolumn -->
In our next example, we want to use out two-column view to display the same data. Please paste the following code into your showall_Two Columns.tpl TPL:
<div class="module albums show-twocolumn"> {if $moduletitle}<h1>{$moduletitle}</h1>{/if} {foreach name=items from=$items item=item} <div class="item {cycle values="column-left,column-right"}"> <h2>{$item->title}</h2> {permissions level=$smarty.const.UILEVEL_NORMAL} <div class="actions"> {if $permissions.edit == 1} {icon controller=albums action=edit id=$item->id title="Edit this `$modelname`"} {/if} {if $permissions.delete == 1} {icon controller=albums action=delete id=$item->id title="Delete this `$modelname`" onclick="return confirm('Are you sure you want to delete this `$modelname`?');"} {/if} {if $permissions.edit == 1} {if $smarty.foreach.items.first == 0} {icon controller=albums action=`rank` img=up.png id=$item->id push=up} {/if} {if $smarty.foreach.items.last == 0} {icon controller=albums action=`rank` img=down.png id=$item->id push=down} {/if} {/if} </div><!-- end actions --> {/permissions} {if $item->artist !="" || $item->year !=""} <ul class="album-data"> {if $item->artist} <li> <h3 class="album-artist"> {$item->artist} </h3> </li> {/if} {if $item->year} <li> <h4 class="album-year"> {$item->year} </h4> </li> {/if} </ul> {/if} {if $item->body} <div class="bodycopy"> {$item->body} </div> {/if} </div><!-- end item --> {/foreach} {clear} <!-- creates a clearing div --> {permissions level=$smarty.const.UILEVEL_NORMAL} {if $permissions.create == 1 || $permissions.edit == 1} {icon controller=albums class="add" action=create text="Create new album" title="Create a new album"} {/if} {/permissions} </div><!-- end show-onecolumn -->
Hopefully we can now see that we can create as many views as we desire using the action name at the beginning of the TPL. We can imagine creating other TPLs as well, ones that use the YUI Javascript library to fade the album information in and out on a carousel of some sort, or maybe even one that uses a flash object to display the data in some fancy way. There are a myriad of possible views we can create!
Example 2 -- Implemented
Now I want to shift gears here and take the same concept of creating multiple views for one action, and move to creating multiple views for a different action rather than showall. Remember that showall was provided automatiucally for us by expController, so we did not have to write extra code to get the data we needed. However, this new function(Action) we will add is not one of the stock actions provided by expController, so we will need to write it ourselves. To do this, we will need to open up our controller and add the new action. Instead of showall which passes to our showall_ views all of the albums in our system, we are going to create an action called showlatest which will pass to our showlatest_ views only the album with the most recent release date. Paste the following code into your albumsController.php:
function showlatest() { global $db; $modelname = $this->basemodel_name; //find the highest year release date $max_Year = $db->max('albums', 'year'); $where = " year = ". $max_Year; $limit = isset($this->params['limit']) ? $this->params['limit'] : null; $order = isset($this->params['order']) ? $this->params['order'] : "`rank` ASC"; //this tells the system to just return the first album it finds that matches that year; if it finds more than one, it will just return the first (simplistic, yes) $record = $this->$modelname->find('first', $where, $order, $limit); assign_to_template(array('record'=>$record, 'modelname'=>$modelname)); }
Make sure that you add at the top of the controller the ability for the user to be able to select your view by adding it to the $useractions array
public $useractions = array('showall'=>'Show all', 'showlatest' =>'Show Latest (Most Recent) Album');
Once this is in place, we want to create two views, showlatest_With Cover.tpl and showlatest_Without Cover.tpl
First, paste the following code into your showlatest_With Year.tpl
<div class="module albums show-latest-withyear"> {if $moduletitle}<h1>{$moduletitle}</h1>{/if} <div class="withyear-wrap"> <div class="record"> <h2>{$record->title}</h2> {permissions level=$smarty.const.UILEVEL_NORMAL} <div class="actions"> {if $permissions.edit == 1} {icon controller=albums action=edit id=$record->id title="Edit this `$modelname`"} {/if} {if $permissions.delete == 1} {icon controller=albums action=delete id=$record->id title="Delete this `$modelname`" onclick="return confirm('Are you sure you want to delete this `$modelname`?');"} {/if} {if $permissions.edit == 1} {if $smarty.foreach.records.first == 0} {icon controller=albums action=`rank` img=up.png id=$record->id push=up} {/if} {if $smarty.foreach.records.last == 0} {icon controller=albums action=`rank` img=down.png id=$record->id push=down} {/if} {/if} </div><!-- end actions --> {/permissions} {if $record->artist !="" || $record->year !=""} <ul class="album-data"> {if $record->artist} <li> <h3 class="album-artist"> {$record->artist} </h3> </li> {/if} {if $record->year} <li> <h4 class="album-year"> {$record->year} </h4> </li> {/if} </ul> {/if} {if $record->body} <div class="bodycopy"> {$record->body} </div> {/if} {clear} </div><!-- end record --> </div><!-- end withyear-wrap --> {permissions level=$smarty.const.UILEVEL_NORMAL} {if $permissions.create == 1 || $permissions.edit == 1} {icon controller=albums class="add" action=create text="Create new album" title="Create a new album"} {/if} {/permissions} </div><!-- end showlatest-withyear -->
And for our second view, please paste into showlatest_Without Year.tpl the following code:
<div class="module albums show-latest-withyear"> {if $moduletitle}<h1>{$moduletitle}</h1>{/if} <div class="withyear-wrap"> <div class="record"> <h2>{$record->title}</h2> {permissions level=$smarty.const.UILEVEL_NORMAL} <div class="actions"> {if $permissions.edit == 1} {icon controller=albums action=edit id=$record->id title="Edit this `$modelname`"} {/if} {if $permissions.delete == 1} {icon controller=albums action=delete id=$record->id title="Delete this `$modelname`" onclick="return confirm('Are you sure you want to delete this `$modelname`?');"} {/if} {if $permissions.edit == 1} {if $smarty.foreach.records.first == 0} {icon controller=albums action=`rank` img=up.png id=$record->id push=up} {/if} {if $smarty.foreach.records.last == 0} {icon controller=albums action=`rank` img=down.png id=$record->id push=down} {/if} {/if} </div><!-- end actions --> {/permissions} {if $record->artist !="" || $record->year !=""} <ul class="album-data"> {if $record->artist} <li> <h3 class="album-artist"> {$record->artist} </h3> </li> {/if} </ul> {/if} {if $record->body} <div class="bodycopy"> {$record->body} </div> {/if} {clear} </div><!-- end record --> </div><!-- end withoutyear-wrap --> {permissions level=$smarty.const.UILEVEL_NORMAL} {if $permissions.create == 1 || $permissions.edit == 1} {icon controller=albums class="add" action=create text="Create new album" title="Create a new album"} {/if} {/permissions} </div><!-- end showlatest-withoutyear -->
Now our albums module has a few new actions and views with which it can be used! Hopefully we have seen how the innards of the exponent 2.0 framework cooperate to both generate data and display it on the page.
For additional information on creating views and view configurations visit the Designer Modules and Views topics.