{ifchanged}

Renders its content when a value differs from the previous row of the loop around it - a heading per group.

Conditions Tag pairs

Syntax

{ifchanged value} ... {/ifchanged}
{ifchanged value, value} ... {/ifchanged}
{ifchanged value} ... @else@ ... {/ifchanged}

Parameters

value
One or more values, usually fields of the current row. The content renders when any of them differs from what it was on the previous row.

Description

{ifchanged $customer} compares its value with the value it had the previous time it ran in the same loop. The content renders when the value is different - and always on the first row - so in a list sorted on that field it renders once at the start of every group: the classic group heading. When the value is the same as before, the @else@ part renders instead, if the tag has one.

With several values - {ifchanged $year, $month} - the content renders when any of them changed. Sort the rows first (the sort option, or in the query): the tag only looks one row back, so an unsorted list gets a heading every time the value flips.

The memory belongs to one run of the enclosing loop - the nearest level that is not an {if}, a {case} or another {ifchanged} - so the tag may stand inside an {if} in the loop, and a loop that runs again (an inner loop on the next outer row) starts afresh. Several {ifchanged} tags in one row are kept apart by position: the second one of a row is compared with the second one of the row before.

Under the strict syntax check an {ifchanged} without a value, or without its closing tag, is an error. The {case} and {if} tags compare with fixed values; {ifchanged} compares with the row before.

Examples

A heading per group

Sorted on the city, the heading renders once at the start of each city.

Templateexamples/ifchanged/1-heading.pad
{offices sort='city'}
  {ifchanged $city}<h4>{$city}</h4>{/ifchanged}
  <p>{$person}</p>
{/offices}
PHPexamples/ifchanged/1-heading.php
<?php

  $offices = [
    [ 'city' => 'Utrecht', 'person' => 'Anna' ],
    [ 'city' => 'Lisbon',  'person' => 'Bruno' ],
    [ 'city' => 'Utrecht', 'person' => 'Carla' ],
    [ 'city' => 'Lisbon',  'person' => 'Dinis' ],
    [ 'city' => 'Oslo',    'person' => 'Eirik' ] ];

?>
Resultopen alone

Lisbon

Bruno

Dinis

Oslo

Eirik

Utrecht

Anna

Carla

Several values and @else@

A change in either value renders the heading; an unchanged row renders the @else@ part.

Templateexamples/ifchanged/2-several.pad
{data 'ifchangedPosts'}
year,month,post
2026,September,Launch
2026,September,First fix
2026,October,Autumn release
2027,October,Next year
{/data}
<ul>
{ifchangedPosts}
  <li>{ifchanged $year, $month}<strong>{$month} {$year}</strong>@else@&mdash; same month{/ifchanged}: {$post}</li>
{/ifchangedPosts}
</ul>
Resultopen alone
  • September 2026: Launch
  • โ€” same month: First fix
  • October 2026: Autumn release
  • October 2027: Next year

See also

  • {if} Renders its content only when a condition holds, with elseif and else branches.
  • {case} Renders the one branch whose {when} matches a value, with an {else} for none.
  • {switch} Answers the next value of a rotating list on every call - striped rows without a counter.