Creating a view

In case you skipped all the JForm pages, this is where our hands-on example continues.

Our component has two views: a list view to show a list of all the items in our jos_folio table, and an edit view that allows you to add new records and edit existing ones.

The list view

There are several files that work together to create the view. We have already created the controller file that calls the view, and the model file that prepares the data. But we have not yet created the view files that display the information.

The view.html.php file

Create the folder /administrator/components/com_folio/views/folios, and within that create a folder called tmpl. Remember to put an index.html file in each folder. Now create the file /administrator/components/com_folio/views/folios/view.html.php. The view.html.php file is where all the toolbar buttons and title for the view are defined, and it calls the model to get the data ready to give to the view.

<?php
defined('_JEXEC') or die;

class FolioViewFolios extends JViewLegacy
{
  protected $items;

  public function display($tpl = null)
  {
    $this->items    = $this->get('Items'),

    if (count($errors = $this->get('Errors')))
    {
      JError::raiseError(500, implode("
", $errors));
      return false;
    }

    $this->addToolbar();
    parent::display($tpl);
  }

  protected function addToolbar()
  {
    $canDo  = FolioHelper::getActions();
    $bar = JToolBar::getInstance('toolbar'),

    JToolbarHelper::title(JText::_('COM_FOLIO_MANAGER_FOLIOS'), ''),

    JToolbarHelper::addNew('folio.add'),

    if ($canDo->get('core.edit'))
    {
      JToolbarHelper::editList('folio.edit'),
    }
    if ($canDo->get('core.admin'))
    {
      JToolbarHelper::preferences('com_folio'),
    }
  }
}

We create the class for the view which is in the form ComponentnameViewViewname, in our case FolioViewFolios. Notice that we are extending from JViewLegacy, as we are using the legacy MVC.

class FolioViewFolios extends JViewLegacy

The first line within that class is where the variable is set up to store the array of data that will be retrieved from the model.

protected $items;

Next is the display function, which is called by default whenever the view is displayed:

public function display($tpl = null)

The $this->get('Items') call gets the data from the model file /administrator/components/com_folio/models/folios.php, and puts it into the items variable that we created earlier.

$this->items    = $this->get('Items'),

Then there is a bit of error checking, just in case something goes wrong with our database query.

if (count($errors = $this->get('Errors')))
{
  JError::raiseError(500, implode("
", $errors));
  return false;
}

The addToolbar function will add all the buttons at the top of the view such as New, Edit, Options, and so on.

$this->addToolbar();

Then finally, we call the parent class display function to show the view:

parent::display($tpl);

The addToolbar function is used for all the buttons that you normally see at the top of the component.

protected function addToolbar()

Next we need to see what permissions the current user has so we can decide which toolbar buttons to display. To do this permission check, we have created a function in our helper file, as we probably want to share this functionality with other views that we add in future. We will create this helper file after we have finished examining this file.

$canDo  = FolioHelper::getActions();

JToolBar::getInstance is called to set up the toolbar so we can start adding the title and buttons to it.

$bar = JToolBar::getInstance('toolbar'),

The text shown at the top of the view is the title, and we are using JText to display a language string COM_FOLIO_MANAGER_FOLIOS, which we will need to add to our language file.

JToolbarHelper::title(JText::_('COM_FOLIO_MANAGER_FOLIOS'), ''),

The button we use to create new records in our database is the New button, which is created using the addNew function. In this case, we are adding a new record to the folio form.

JToolbarHelper::addNew('folio.add'),
The view.html.php file

The edit button is used in conjunction with the checkbox next to each row of data, where a user can select a record and click on Edit to open that record and change the data. Before we show the edit button, we first check to make sure the current user has edit permission for this component.

if ($canDo->get('core.edit'))
{
  JToolbarHelper::editList('folio.edit'),
}
The view.html.php file

Components usually show an Options button in the default view, which opens up the component options (also known as parameters) and component permissions. Before we show the options button, we need to check to make sure the current user has admin permission for this component also known as the configure action.

if ($canDo->get('core.admin'))
{
  JToolbarHelper::preferences('com_folio'),
}
The view.html.php file

We should add a language string for the title we used in this view to our language file, so open up /administrator/components/com_folio/language/en-GB/en-GB.com_folio.ini and add the following:

COM_FOLIO_MANAGER_FOLIOS="Folio Manager: Folios"

The helper file

Now would be a good time to actually create our helper file, so create the file /administrator/components/com_folio/helpers/folio.php and add the following:

<?php
defined('_JEXEC') or die;

class FolioHelper
{
  public static function getActions($categoryId = 0)
  {
    $user  = JFactory::getUser();
    $result  = new JObject;

    if (empty($categoryId))
    {
      $assetName = 'com_folio';
      $level = 'component';
    }
    else
    {
      $assetName = 'com_folio.category.'.(int) $categoryId;
      $level = 'category';
    }

    $actions = JAccess::getActions('com_folio', $level);

    foreach ($actions as $action)
    {
      $result->set($action->name,  $user->authorise($action->name, $assetName));
    }

    return $result;
  }
}

The class is in the form ComponentnameHelper, in our case FolioHelper.

class FolioHelper

We created a getActions function that is used to check to see what permissions the current user has. Essentially, it is just looking at the component permission settings for the groups that this user is in.

public static function getActions($categoryId = 0)

The view layout file

Within the /administrator/components/com_folio/views/folios/tmpl folder, create the file default.php, which is the actual view that is displayed. By default, Joomla! expects to find a layout called default for list views.

<?php
defined('_JEXEC') or die;

$listOrder  = '';
$listDirn  = '';
?>

<form action="<?php echo JRoute::_('index.php?option=com_folio&view=folios'), ?>" method="post" name="adminForm" id="adminForm">
  <div id="j-main-container" class="span10">

    <div class="clearfix"> </div>
    <table class="table table-striped" id="folioList">
      <thead>
        <tr>
          <th width="1%" class="hidden-phone">
            <input type="checkbox" name="checkall-toggle" value="" title="<?php echo JText::_('JGLOBAL_CHECK_ALL'), ?>" onclick="Joomla.checkAll(this)" />
          </th>
          <th class="title">
            <?php echo JHtml::_('grid.sort', 'JGLOBAL_TITLE', 'a.title', $listDirn, $listOrder); ?>
          </th>
        </tr>
      </thead>
      <tbody>
      <?php foreach ($this->items as $i => $item) :
        ?>
        <tr class="row<?php echo $i % 2; ?>">
          <td class="center hidden-phone">
            <?php echo JHtml::_('grid.id', $i, $item->id); ?>
          </td>
          <td class="nowrap has-context">
            <a href="<?php echo JRoute::_('index.php?option=com_folio&task=folio.edit&id='.(int) $item->id); ?>">
              <?php echo $this->escape($item->title); ?>
            </a>
          </td>
        </tr>
        <?php endforeach; ?>
      </tbody>
    </table>

    <input type="hidden" name="task" value="" />
    <input type="hidden" name="boxchecked" value="0" />
    <input type="hidden" name="filter_order" value="<?php echo $listOrder; ?>" />
    <input type="hidden" name="filter_order_Dir" value="<?php echo $listDirn; ?>" />
    <?php echo JHtml::_('form.token'), ?>
  </div>
</form>

We are not actually using the listOrder and listDirn variables yet, we will use these later when we implement sorting on the columns in the view.

$listOrder  = '';
$listDirn  = '';

All the fields in the view are displayed within a form, which is submitted whenever someone changes one of the view filters or clicks the pagination, both of which we are not going to implement in our component yet. The URL the form goes to is passed through the JRoute function, which helps with routing and allows Joomla! to keep track of the currently active menu item. Whenever this form is submitted, it just goes back to the same view you are currently in, which is also the default view in our component. The name and id of adminForm is important, if you leave these out then the buttons on your form such as Save and Close will not work.

<form action="<?php echo JRoute::_('index.php?option=com_folio&view=folios'), ?>" method="post" name="adminForm" id="adminForm">

To be consistent with the appearance of the core components, we will wrap our table in a couple of divs.

<div id="j-main-container" class="span10">

  <div class="clearfix"> </div>
  <table class="table table-striped" id="folioList">

We only have two columns in our view so far, the checkbox that allows you to select an item prior to clicking on Edit, and the title column. Notice the hidden-phone class applied to the checkall column. This is one of the styles in Bootstrap that will hide this content when viewed on a mobile device. For the first column checkall, instead of showing a text title, we will put a checkbox that will select all items currently shown on the view rather than the user having to select each one individually. The title column will display the text JGLOBAL_TITLE, which is defined in one of the core language files. You could put your own custom language string in here instead to display some other text, if you wanted.

<th width="1%" class="hidden-phone">
  <input type="checkbox" name="checkall-toggle" value="" title="<?php echo JText::_('JGLOBAL_CHECK_ALL'), ?>" onclick="Joomla.checkAll(this)" />
</th>
<th class="title">
  <?php echo JHtml::_('grid.sort', 'JGLOBAL_TITLE', 'a.title', $listDirn, $listOrder); ?>
</th>

Note

Bootstrap class hidden-tablet can be used to hide content when displayed on a tablet device such as an iPad. You could also use hidden-desktop for content that you want to hide when viewed on desktop computers, but want to show on tablet devices and mobile devices such as iPhone, Android, or Blackberry.

After displaying the column titles, we look through the data in the $this->items variable. For each record, we are going to display a checkbox to select that individual item, and a title which is clickable to open up that record. Notice how we are using the JRoute function again to make sure clicking on this link doesn't have any SEF issues. &task=folio.edit tells Joomla! that we want to edit the folio view, and then we pass the id number so that we know which individual record to display in this view.

<?php foreach ($this->items as $i => $item) :
  ?>
  <tr class="row<?php echo $i % 2; ?>">
    <td class="center hidden-phone">
      <?php echo JHtml::_('grid.id', $i, $item->id); ?>
    </td>
    <td class="nowrap has-context">
      <a href="<?php echo JRoute::_('index.php?option=com_folio&task=folio.edit&id='.(int) $item->id); ?>">
        <?php echo $this->escape($item->title); ?>
      </a>
    </td>
  </tr>
<?php endforeach; ?>

There are some hidden fields at the bottom of the view that allow Joomla! to pass to the form the task we are performing, such as publish, unpublish, archive, and so on, which we will talk about later. The boxchecked value is used to determine which items have the checkbox next to them selected. Filter_order and filter_order_dir are used to determine which column we are sorting by and whether this is ascending or descending.

    <input type="hidden" name="task" value="" />
    <input type="hidden" name="boxchecked" value="0" />
    <input type="hidden" name="filter_order" value="<?php echo $listOrder; ?>" />
    <input type="hidden" name="filter_order_Dir" value="<?php echo $listDirn; ?>" />

The token number we are passing to the form at the end is for security purposes. This ensures that the form that is submitted is from the same Joomla! site and not a Cross Site Request Forgery (CSRF) attack. Joomla! will check this token using JSession::checkToken() to prevent CSRF attacks.

<?php echo JHtml::_('form.token'), ?>

If you take a look at our view, you should see the following:

The view layout file

The edit view

The edit view is the form that you use when creating a new record or editing an existing one. It should have the singular version of the plural name you used for your list view. Since our list view was called folios, we will call our edit view folio. If your list view was called books, your edit view would be book, or another example is if the list view was called cars, then the edit view would be called car.

Create the folders /administrator/components/com_folio/views/folio and /administrator/components/com_folio/views/folio/tmpl, making sure you put an index.html file in each.

The view.html.php file

Create the file /administrator/components/com_folio/views/folio/view.html.php and add the following code:

<?php
defined('_JEXEC') or die;

class FolioViewFolio extends JViewLegacy
{
  protected $item;

  protected $form;

  public function display($tpl = null)
  {
    $this->item    = $this->get('Item'),
    $this->form    = $this->get('Form'),

    if (count($errors = $this->get('Errors')))
    {
      JError::raiseError(500, implode("
", $errors));
      return false;
    }

    $this->addToolbar();
    parent::display($tpl);
  }

  protected function addToolbar()
  {
    JFactory::getApplication()->input->set('hidemainmenu', true);

    JToolbarHelper::title(JText::_('COM_FOLIO_MANAGER_FOLIO'), ''),

    JToolbarHelper::save('folio.save'),

    if (empty($this->item->id))
    {
      JToolbarHelper::cancel('folio.cancel'),
    }
    else
    {
      JToolbarHelper::cancel('folio.cancel', 'JTOOLBAR_CLOSE'),
    }
  }
}

The class name is in the form ComponentnameViewViewname, in this case FolioViewFolio, and we are extending JViewLegacy as we are using the legacy MVC model:

class FolioViewFolio extends JViewLegacy

We will create two variables, an item array to store the data retrieved from the model, and a form variable used to build our form.

protected $item;

protected $form;

Like the list view, the display function is called by default whenever we display this view, which in turn calls the addToolbar function to add our title and buttons at the top.

public function display($tpl = null)

The next lines load the data from the model and build our JForm ready to be displayed in the view.

$this->item    = $this->get('Item'),
$this->form    = $this->get('Form'),

In case our model has a problem, we have some error checking here. An example of when an error may occur is if one of the fields is missing from our database table, which could happen if the software is upgraded to a newer version and the update script hasn't added all the new fields.

if (count($errors = $this->get('Errors')))
{
  JError::raiseError(500, implode("
", $errors));
  return false;
}

If there are no errors, we will display the toolbar, and then the rest of the view:

$this->addToolbar();
parent::display($tpl);

We need to create our addToolbar function which controls which buttons are shown at the top of our view.

protected function addToolbar()

Now here is something that is not in the list view: we are going to hide the main menu so we don't see links to the other views. Since our component doesn't have any other views, it's not really an issue yet, but later on when we add more views it would be come a problem.

JFactory::getApplication()->input->set('hidemainmenu', true);

The title at the top of the page is shown before we start to add buttons. We will need to add a language string for this title.

JToolbarHelper::title(JText::_('COM_FOLIO_MANAGER_FOLIO'), ''),

The first button we will add is the Save button, which is pretty self-explanatory.

JToolbarHelper::save('folio.save'),
The view.html.php file

The second button we are going to add is a little bit fancier. This will show a Cancel button if you create a new record, or a Close button if you are editing an existing record.

if (empty($this->item->id))
{
  JToolbarHelper::cancel('folio.cancel'),
}
else
{
  JToolbarHelper::cancel('folio.cancel', 'JTOOLBAR_CLOSE'),
}
The view.html.php file
The view.html.php file

We will need to add the new language strings we have used in these files to our language file /administrator/components/com_folio/language/en-GB/en-GB.com_folio.ini.

COM_FOLIO_MANAGER_FOLIO="Manage Folio"

The view layout file

The view itself is in the /administrator/components/com_folio/views/folio/tmpl folder. So within this folder create an edit.php file which is the name used by default for form layouts.

<?php
defined('_JEXEC') or die;

?>

<form action="<?php echo JRoute::_('index.php?option=com_folio&layout=edit&id='.(int) $this->item->id); ?>" method="post" name="adminForm" id="adminForm" class="form-validate">
  <div class="row-fluid">
    <div class="span10 form-horizontal">

  <fieldset>
    <?php echo JHtml::_('bootstrap.startPane', 'myTab', array('active' => 'details')); ?>

      <?php echo JHtml::_('bootstrap.addPanel', 'myTab', 'details', empty($this->item->id) ? JText::_('COM_FOLIO_NEW_FOLIO', true) : JText::sprintf('COM_FOLIO_EDIT_FOLIO', $this->item->id, true)); ?>
        <div class="control-group">
          <div class="control-label"><?php echo $this->form->getLabel('title'), ?></div>
          <div class="controls"><?php echo $this->form->getInput('title'), ?></div>
        </div>
      <?php echo JHtml::_('bootstrap.endPanel'), ?>

      <input type="hidden" name="task" value="" />
      <?php echo JHtml::_('form.token'), ?>

    <?php echo JHtml::_('bootstrap.endPane'), ?>
    </fieldset>
    </div>
  </div>
</form>

The fields on the page are displayed within a form, so when you submit the form by hitting the Save button it will be able to access all the data entered. We are passing the URL through the JRoute function, which will avoid SEF issues. Notice the form-validate class, which allows us to set some fields as mandatory in our XML file we created earlier, /administrator/components/com_folio/models/forms/folio.xml.

<form action="<?php echo JRoute::_('index.php?option=com_folio&layout=edit&id='.(int) $this->item->id); ?>" method="post" name="adminForm" id="adminForm" class="form-validate">

To make the form look like the core components, we will wrap the fields in a couple of divs.

<div class="row-fluid">
  <div class="span10 form-horizontal">

Note

Bootstrap uses a 12 column grid, so span10 will use ten twelfths of the available space.

Instead of using expandable sections like in previous Joomla! versions, Joomla! 3 uses Bootstrap to create tabs. The title on our tab will change depending on whether you are creating a new item or editing an existing one. We will need to add these new language strings to our language file.

<?php echo JHtml::_('bootstrap.startPane', 'myTab', array('active' => 'details')); ?>

  <?php echo JHtml::_('bootstrap.addPanel', 'myTab', 'details', empty($this->item->id) ? JText::_('COM_FOLIO_NEW_FOLIO', true) : JText::sprintf('COM_FOLIO_EDIT_FOLIO', $this->item->id, true)); ?>

Each field we want to display on the form is displayed using JForm. In our case, we are only showing one field, however we will add more fields to our component in the next chapter. We need to ask JForm to retrieve the label for our field, and the field itself, which is all based on what we set up in /administrator/components/com_folio/models/forms/folio.xml.

<div class="control-group">
  <div class="control-label"><?php echo $this->form->getLabel('title'), ?></div>
  <div class="controls"><?php echo $this->form->getInput('title'), ?></div>
</div>

Potentially we could add more tabs to our form, but for now we don't have any others, so we will close the tab panel.

<?php echo JHtml::_('bootstrap.endPanel'), ?>

We have a hidden field used to determine what task we are performing, such as save.

<input type="hidden" name="task" value="" />

Like the list view, we have a form token to prevent CSRF attacks:

<?php echo JHtml::_('form.token'), ?>

We then close off the Bootstrap pane, the fieldset, divs, and the form.

Since we have used a couple of new language strings, open up your /administrator/components/com_folio/language/en-GB/en-GB.com_folio.ini file and add the following:

COM_FOLIO_EDIT_FOLIO="Edit Folio"
COM_FOLIO_NEW_FOLIO="New Folio"

We are going to build on this component over the next couple of chapters to make it actually useful. Go ahead and try it out, you should now be able to create new items, enter a title, and save the form. You can also edit the form and change the title.

The view layout file
The view layout file

You will also notice that if you shrink the width of your browser window, the checkbox column will disappear since we have given this column a hidden-phone class.

The view layout file
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.16.48.181