Forum

Thread tagged as: Question

Adding Next / Previous links to detail page of a list/detail setup

Hi,

For projects with list/detail setups, I like giving visitors the opportunity to click Next & Previous links so they can cycle through all the items in a list/detail setup. For example, I'm working on a site with a portfolio of finished projects. Each project has a page thanks to the list/detail setup and the Next and Previous links work. But only if I put them above or below the main content that's output from the detail template.

How do I add Next and Previous links that cycle through all the pages in a list/detail setup elsewhere in the layout so that they're essentially part of the main detail template's layout?

For example, instead of:

< Previous project | Next Project >

Project Name

Image

Description

I might want to have:

Project Name

Image

Sidebar with <Previous project | Next project >

Description

My detail template looks like this:

<?php 
     $result = perch_content_custom('Projects', array(
     'page' => '/projects/index.php',
     'template' => 'listdetail_detail.html',
     'filter' => 'slug',
     'match' => 'eq',
     'value' => perch_get('s'),
     'count' => 1,
     'skip-template' => true,
     'return-html' => true,
));
?>

        <p><?php
    PerchSystem::set_var('is_prev', true);

    perch_content_custom('Projects', array(
    'page' => '/projects/index.php',
    'template'   => 'listdetail_prevnext.html',
    'filter'     => '_order',
    'match'      => 'lt',
    'value'      => $result[0]['_sortvalue'],
    'sort'       => '_order',
    'sort-order' => 'DESC',
    'count'      => 1,
)); 

    PerchSystem::set_var('is_prev', false);

perch_content_custom('Projects', array(
    'page' => '/projects/index.php',
    'template'   => 'listdetail_prevnext.html',
    'filter'     => '_order',
    'match'      => 'gt',
    'value'      => $result[0]['_sortvalue'],
    'sort'       => '_order',
    'sort-order' => 'ASC',
    'count'      => 1,
)); 
?>
</p>


<?php
    echo $result['html'];
?>

Again, that code above works just fine, but restricts me to having those Next and Previous links above (or below) the $result['html'] code that gets displayed.

How can I incorporate those links within the main layout from the detail template itself? Anyone accomplished this?

Thanks!

Franz Neumann

Franz Neumann 0 points

  • 2 years ago
Hussein Al Hammad

Hussein Al Hammad 105 points
Registered Developer

Hello Franz,

There's more than one way to accomplish this.

One way would be to skip the templating like you're doing, getting the next and previous items, set them as variables then call perch_content_custom() again to output to the page:

$result = perch_content_custom('Projects', array(
'page' => '/projects/index.php',
'filter' => 'slug',
'match' => 'eq',
'value' => perch_get('s'),
'count' => 1,
'skip-template' => true,
));


// get $next and $prev like you're already doing, but use skip-template


// set vars using values from $next and $prev to be available in template
PerchSystem::set_vars([
'next_slug' => $next[0]['slug'],
'next_title' => $next[0]['title'],
'prev_slug' => $prev[0]['slug'],
'prev_title' => $prev[0]['title'],
]);


// output to page
perch_content_custom('Projects', array(
'page' => '/projects/index.php',
'template' => 'listdetail_detail.html',
'filter' => 'slug',
'match' => 'eq',
'value' => perch_get('s'),
'count' => 1,
));

Another way is to make use of the perch_template() function. This may be a good use case for it. I wrote a blog post about using it here: https://grabapipit.com/blog/rendering-templates-on-the-fly

Skip the templating for all items (current, next and prev), then use perch_template() to output the content:

// get current
$result = perch_content_custom('Projects', array(
'page' => '/projects/index.php',
'filter' => 'slug',
'match' => 'eq',
'value' => perch_get('s'),
'count' => 1,
'skip-template' => true,
));


// get $next and $prev like you're already doing, but use skip-template
$prev = perch_content_custom('Projects', array(
'page' => '/projects/index.php',
'filter' => '_order',
'match' => 'lt',
'value' => $result[0]['_sortvalue'],
'sort' => '_order',
'sort-order' => 'DESC',
'count' => 1,
'skip-template' => true
)); 


$next = perch_content_custom('Projects', array(
'page' => '/projects/index.php',
'filter' => '_order',
'match' => 'gt',
'value' => $result[0]['_sortvalue'],
'sort' => '_order',
'sort-order' => 'ASC',
'count' => 1,
'skip-template' => true
)); 

// create $data array
// add current item to array
$data = $result[0]; 

// add next and prev values to array
$data['next_slug'] = $next[0]['slug'];
$data['next_title'] = $next[0]['title'];
$data['prev_slug'] = $prev[0]['slug'];
$data['prev_title'] = $prev[0]['title'];

// render the data in a template
perch_template('content/listdetail_detail.html', $data);

Then you can use next_slug, next_title, etc inside the template:

<a href="/projects/<perch:content id="next_slug">">Next: <perch:content id="title"></a>

Using the same approach (perch_template()) if you want all the fields for next/prev to be available inside the template, you can modify your $data array to be like this:

$data = $result[0];
$data['next'] = $next;
$data['prev'] = $prev;
perch_template('content/listdetail_detail.html', $data);

Then inside the template you can render 'next' and 'prev' inside repeaters:

<perch:repeater id="next">
    <a href="/projects/<perch:content id="slug">">Next: <perch:content id="title"></a>
</perch:repeater>


<perch:repeater id="prev">
    <a href="/projects/<perch:content id="slug">">Prev: <perch:content id="title"></a>
</perch:repeater>
Hussein Al Hammad

Hussein Al Hammad 105 points
Registered Developer

You can also make use of the each option:

$result = perch_content_custom('Projects', array(
    'page' => '/projects/index.php',
    'template' => 'listdetail_detail.html',
    'filter' => 'slug',
    'match' => 'eq',
    'value' => perch_get('s'),
    'count' => 1,
    'skip-template' => true,
    'return-html' => true,
    'each' => function($item) {
        // get prev
        $prev = perch_content_custom('Projects', array(
            'page' => '/projects/index.php',
            'filter' => '_order',
            'match' => 'lt',
            'value' => $item['_sortvalue'],
            'sort' => '_order',
            'sort-order' => 'DESC',
            'count' => 1,
            'skip-template' => true
        )); 

        // get next 
        $next = perch_content_custom('Projects', array(
            'page' => '/projects/index.php',
            'filter' => '_order',
            'match' => 'gt',
            'value' => $item['_sortvalue'],
            'sort' => '_order',
            'sort-order' => 'ASC',
            'count' => 1,
            'skip-template' => true
        )); 

        // add next/prev to item
        $item['prev'] = $prev;
        $item['next'] = $next;

        return $item;
    }
));



echo $result['html'];

Hussein,

Thanks so much for your help! I used the last (each) option and I can now put the next/prev links anywhere in my main list_detail.html template.

Piggy-backing on your code, I added the ability to create a linked list of all the items in the list/detail setup, in case anyone else is interested.

I amended the code above with:

// get all items
$all = perch_content_custom('Projects', array(
'page' => '/projects/index.php',
'sort' => '_order',
'sort-order' => 'ASC',
'count' => 1000,
'skip-template' => true ));

// add all/next/prev to item
$item['prev'] = $prev;
$item['next'] = $next;
$item['all'] = $all;
return $item; } ));

Then, in the list_detail.html template, I used:

<ul>
    <perch:repeater id="all">
        <li><a href="/projects/<perch:content id="slug" type="slug" />"><perch:content id="project_title"></a></li>
    </perch:repeater>
</ul>

I'm not sure if that's the most efficient way of doing that, but it seems to work.

Hussein Al Hammad

Hussein Al Hammad 105 points
Registered Developer

Good stuff, Franz.

I'm not sure if that's the most efficient way of doing that, but it seems to work.

You can also return the templated content:

$next = perch_content_custom('Projects', array(
'page' => '/projects/index.php',
'filter' => '_order',
'match' => 'gt',
'value' => $item['_sortvalue'],
'sort' => '_order',
'sort-order' => 'ASC',
'count' => 1,
'template' => 'next_item.html'
), true); 

$item['next'] = $next;
return $item;

So your next_item.html would have the markup and Perch tags you need. And in listdetail_detail.html you would only add one tag and add the html attribute to it:

<perch:content id="next" type="hidden" html>

As you see there are many ways that gets you the same result.

I think skipping template and outputting the items inside a repeater may lead to limited functionality. Not sure whether you would be able to use perch:categories and perch:related inside the repeater with this approach. Also some field types may also lose their functionality like the youtube and map field types.

I'm finding that the perch:repeater tags make those enclosed fields show up in the edit screen, which could be confusing to editors.

<perch:repeater id="next" label="Next link (ignore)"> <p>Next project: <a href="/projects/<perch:content id="slug" >"><perch:content id="project_title"></a> ›</p> </perch:repeater>

Tried using suppress, but that didn't do anything; I guess suppress doesn't really work in this context.

Hussein Al Hammad

Hussein Al Hammad 105 points
Registered Developer

A better approach would be to use different templates for the edit form in the control panel and for displaying the content on the site. The template used for editing doesn't need the repeater tags. Additional tags you add to the other template won't reflect on the edit form.

I also wanted info about that thanks for your answers

https://www.whatsappstatusbox.in