Code snippets for symfony 1.x

Navigation

Refine Tags

Snippets tagged "css pager"

Complimentary Filters

A common modification to a CRUD module is filtering records on the list page. There are probably several nice ways to do this, including drop-downs, forms, etc. depending on the situation. While some of these approaches are nice, they are often not minimal... We like minimal!

Discussion

Say you have a book table, with a related author and genre. You want to filter the list of books by those related tables with links, paginate your list, and make it sortable via links in the header of the table.

To do this traditionally, you'll need lots of nasty little if statements in your template code, to check for all of these parameters (author_id, genre_id, title, num_pages, page, etc.) and combine them all together into a meaningful uri for your link_to function (something like "book/list?author_id=10&genre_id=5&sort=title&page=5"). We still want that link in the end, but generating it... How about a better way!

Followup Example

<!-- listSuccess.php -->
<?php use_helpers('Filter', 'Pagination') ?>
<h2>Books</h2>
<h3>Filter By</h3>
<table class="filters">
  <tbody>
    <tr>
      <th>Author:</th>
      <td><?php echo filter_navigation(objects_for_filter($authors), 'author_id', $author_id) ?></td>
    </tr>
    <tr>
      <th>Genre:</th>
      <td><?php echo filter_navigation(objects_for_filter($genres), 'genre_id', $genre_id) ?></td>
    </tr>
  </tbody>
</table>
<hr />
<table class="list">
  <thead>
    <tr>
      <th><?php link_to_unless($sort == 'id', 'Id', filter_url('sort', 'id')) ?></th>
      <th><?php link_to_unless($sort == 'title', 'Title', filter_url('sort', 'title')) ?></th>
      <th><?php link_to_unless($sort == 'author_id', 'Author', filter_url('sort', 'author_id')) ?></th>
      <th><?php link_to_unless($sort == 'genre_id', 'Genre', filter_url('sort', 'genre_id')) ?></th>
    </tr>
  </thead>
  <tbody>
    <?php foreach ($pager->getResults() as $book): ?>
      <tr>
        <td><?php echo $book->getId() ?></td>
        <td><?php echo $book->getTitle() ?></td>
        <td><?php echo $book->getAuthor()->getName() ?></td>
        <td><?php echo $book->getGenre()->getName() ?></td>
      </tr>
    <?php endforeach; ?>
  </tbody>
</table>
<?php echo pager_navigation($pager) ?>

NOTE: pager_navigation is covered at http://www.symfony-project.com/snippets/snippet/4, but needs to guess the uri, which is done at http://www.symfony-project.com/snippets/snippet/59.

NOTE: filter_navigation returns an unordered list, so you'll need css to display the <li> tags inline, and remove <ul> padding, margin, etc.

I'll leave it as an exercise to the reader to create the controller (action) code for this template, but it should be obvious.

The Code

<?php
 
/**
 * Generate a url using the current internal uri, but replaces a param with a new value.
 * If the param is not in the current uri's query string, it is added instead.
 *
 * This is useful for a page that uses several filters to record sets,
 * and needs all the filters to work together, instead of blasting each
 * other away when a new link is clicked.
 *
 * <strong>Examples:</strong>
 * <code>
 *  // with current uri => mymodule/myaction?author=10&genre=3
 *
 *  echo link_to('new author', filter_url('author', 5));
 *  // uri when clicked => mymodule/myaction?author=5&genre=3
 *
 *  echo link_to('new genre', filter_url('genre', 1));
 *  // uri when clicked => mymodule/myaction?author=10&genre=1
 *
 *  // with current uri => mymodule/myaction
 *
 *  echo link_to('an author', filter_url('author', 10));
 *  // uri when clicked => mymodule/myaction?author=10
 * </code>
 *
 * @param string the name of the parameter to replace
 * @param string the value to replace the current value with
 * @param boolean use route name
 * @return string the url with the parameter replaced
 * @see link_to
 */
function filter_url($param, $new_value, $with_route_name = false)
{
    // fetch params from query string
    $params = _get_params(_get_query_string());
 
    // replace param with new value
    $params[$param] = $new_value;
 
    return _get_uri($with_route_name) . '?' . _build_query_string($params);
}
 
/**
 * Removes a parameter from the current uri and returns the resulting url.
 *
 * @see filter_url
 */
function remove_filter_url($param, $with_route_name = false)
{
    // fetch params from query string
    $params = _get_params(_get_query_string());
 
    // remove param
    unset($params[$param]);
 
    return _get_uri($with_route_name) . '?' . _build_query_string($params);
}
 
/**
 * Generates an unordered list of links to filter the current record set by.
 * Multiple sets of filter_navigation links will work together, using the current uri.
 *
 * <strong>Examples:</strong>
 * <code>
 *  echo filter_navigation(array(10=>'Jones', 12=>'Smith, J.', 13=>'Darby'), 'author_id', 13);
 *  echo filter_navigation(objects_for_filter($authors), 'author_id', 13);
 * </code>
 *
 * @param array list of key=>value pairs of ids and strings
 * @param string the name of the parameter for this filter
 * @param string the selected id (or null, if none selected)
 * @param string the text to use for the "all" link
 * @see filter_url
 */
function filter_navigation($list, $param, $selected = null, $all_text = 'All')
{
    $html = '';
 
    $html .= content_tag('li', link_to_unless($selected === null, $all_text, remove_filter_url($param)));
    foreach ($list as $key => $value)
    {
        $html .= content_tag('li', link_to_unless($selected == $key, $value, filter_url($param, $key)));
    }
 
    return content_tag('ul', $html);
}
 
/**
 * Generates a simple list from a record set of propel objects.
 * Expects a getId function and a toString function.
 *
 * @param array objects to be converted to a list
 * @see filter_navigation
 */
function objects_for_filter($objects)
{
    $list = array();
 
    foreach ($objects as $object)
    {
        $list[$object->getId()] = $object->toString();
    }
 
    return $list;
}
 
function _get_uri($with_route_name = false)
{
    $internal_uri = sfRouting::getInstance()->getCurrentInternalUri($with_route_name);
    $ar = explode('?', $internal_uri);
 
    return ($with_route_name ? '@' : '') . $ar[0];
}
 
function _get_query_string()
{
    $internal_uri = sfRouting::getInstance()->getCurrentInternalUri();
    $ar = explode('?', $internal_uri);
 
    return isset($ar[1]) ? $ar[1] : '';
}
 
function _get_params($query_string)
{
    // parse query string into associative array
    $params = array();
    if ($query_string != '')
    {
        foreach (explode('&', $query_string) as $kvpair)
        {
            list($key, $value) = explode('=', $kvpair);
            $params[$key] = $value;
        }
    }
 
    return $params;
}
 
function _build_query_string($params)
{
    // build list of key=value strings
    $ar = array();
    foreach ($params as $key => $value)
    {
        $ar[] = $key . '=' . $value;
    }
 
    return implode('&', $ar);
}

NOTE: Place this in apps/myapp/lib/helper/FilterHelper.php.

Additional Usage Examples

<?php echo link_to('new author', filter_url('author_id', 10)) ?>
<?php echo url_for(filter_url('author_id', 10)) ?>
<?php echo link_to_if($condition, 'new author',  filter_url('author_id', 10)) ?>
<?php echo link_to_unless($condition, 'new author',  filter_url('author_id', 10)) ?>
<?php echo button_to('new author',  filter_url('author_id', 10)) ?>

Additional Helpers

<?php
 
/**
 * Shortcut combining link_to and filter_url into single function.
 *
 * @see link_to
 * @see filter_url
 */
function link_to_filter($name, $param, $new_value, $options = array())
{
    return link_to($name, filter_url($param, $new_value), $options);
}
 
/**
 * Shortcut combining url_for and filter_url into single function.
 *
 * @see url_for
 * @see filter_url
 */
function filter_url_for($param, $new_value)
{
    return url_for(filter_url($param, $new_value));
}
 
/**
 * Shortcut combining link_to_if and filter_url into single function.
 *
 * @see link_to_if
 * @see filter_url
 */
function link_to_filter_if($condition, $name, $param, $new_value, $options = array())
{
    return link_to_if($condition, $name, filter_url($param, $new_value), $options);
}
 
/**
 * Shortcut combining link_to_unless and filter_url into single function.
 *
 * @see link_to_unless
 * @see filter_url
 */
function link_to_filter_unless($condition, $name, $param, $new_value, $options = array())
{
    return link_to_unless($condition, $name, filter_url($param, $new_value), $options);
}
 
/**
 * Shortcut combining button_to and filter_url into single function.
 *
 * @see button_to
 * @see filter_url
 */
function button_to_filter($name, $param, $new_value, $options = array())
{
    return button_to($name, filter_url($param, $new_value), $options);
}
by Stephen Riesenberg on 2007-02-03, tagged css  filter  helper  pager  pagination  template  view 

Minimal CSS pagination helper

This is helper is mostly inspired by Pagination navigation helper, but there are some differences:

PaginationHelper.php

function pagination($pager)
{
    $uri = sfRouting :: getInstance()->getCurrentInternalUri();
    $html = '';
 
    if ($pager->haveToPaginate())
    {
        $uri .= strstr($uri, '?') ? '&page=' : '?page=';
 
        if ($pager->getPage() != 1)
        {
            $html .= '<li>' . link_to('first', $uri . '1') . '</li>';
            $html .= '<li>' . link_to('previous', $uri . $pager->getPreviousPage()) . '</li>';
        }
 
        foreach ($pager->getLinks() as $page)
        {
            if ($page == $pager->getPage())
                $html .= '<li><strong>' . link_to($page, $uri . $page) . '</strong></li>';
            else
                $html .= '<li>' . link_to($page, $uri . $page) . '</li>';
        }
 
        if ($pager->getPage() != $pager->getLastPage())
        {
            $html .= '<li>' . link_to('next', $uri . $pager->getNextPage()) . '</li>';
            $html .= '<li>' . link_to('last', $uri . $pager->getLastPage()) . '</li>';
        }
 
        $html = '<ul class="pagination">' . $html . '</ul>';
    }
 
    return $html;
}

Minimal CSS

ul.pagination li {
    display: inline;
    list-style-type: none;
    padding-right: 1em;
}

In your template

<?php echo use_helper('Pagination') ?>
<?php echo pagination($pager) ?>
by brikou on 2006-07-19, tagged css  helper  pager  pagination  propel 
(6 comments)