Skip to main content

This site requires you to update your browser. Your browsing experience maybe affected by not having the most up to date version.

General Questions /

General questions about getting started with SilverStripe that don't fit in any of the categories above.

Moderators: martimiz, Sean, biapar, Willr, Ingo, swaiba, simon_w

[SOLVED] Strange template include/loop order in SS3


Reply


7 Posts   934 Views

Avatar
blueskies

Community Member, 42 Posts

16 January 2013 at 7:17am

Sorry for double posting, but I posted this in "Upgrading Silverstripe" and got no response. I was hoping someone here could help me.....

Okay, I have run into the following predicament and I'm not sure if this is a bug or intended behaviour, but it affects quite a bit of a project I'm upgrading.

In a template I have the following code:

<% if Results %>
<table class="records items">
<% loop Results %>
LOOP: $Pos
<% include ResultsTable %>

<% end_loop %>
</table>
<% end_if%>

Which grabs the results from a search and plops them into a template. But the table part I reuse in other areas, so it is included. The table include looks like this:

<% if First %>
   <tr class="heading">
      <th>INCLUDE $Pos</th>

      <% control ColHeadings %>
      <th>$Value</th>
      <% end_control %>
   </tr>
<% end_if %>

   <tr<% if Even %> class="zebra"<% end_if %>>
      <td></td>
      <% control RowValues %>
         <td>$Value</td>
      <% end_control %>
   </tr>

All the code works except I'm getting an unintended result: Every time the include runs, the "if first" evaluates to true... every time. The previous (2.*) versions of Silverstripe would first include the resultstable and THEN loop over it, with the "if first" only being true one time. The new (3.0.3) version seems to include that template every time it loops, which sets the iterator back to one every time.

Notice the $Pos vars in the templates: LOOP $Post evaluates to the correct number (LOOP 1, LOOP 2, LOOP 3, etc). But the INCLUDE $Pos is always 1.

Is this a bug or intended behaviour? If it is intended, then how am I supposed to order the includes/loop in order to have "if first" evaluate true only once?

-----------------
Don't know if it's relevant, but the table is populated by the following code:

....
$query = $context->getQuery($searchCriteria, $Sort, array('start'=>$start,'limit'=>$limit));
$records = $context->getResults($searchCriteria, $Sort);
if($records) {
$records = new PaginatedList($records, $request);
}
return $records;

Avatar
copernican

Community Member, 189 Posts

18 January 2013 at 2:22am

I believe that this is bug and not intended. I would check [url]http://open.silverstripe.org/[/url] and see if its been submitted as a bug yet. If not, maybe submit a ticket yourself.

I've ran into this problem myself and just opted to not use the include until its resolved.

Avatar
blueskies

Community Member, 42 Posts

19 January 2013 at 9:50am

Thanks for your reply. That's what I'm afraid of. Just hoping I'm not the only one who is using Pos,First,or Last inside an include, which is included inside a loop...

Hoping I did something wrong so it's a quick fix...

Avatar
blueskies

Community Member, 42 Posts

27 January 2013 at 9:59am

I got a reply by submitting this as a bug, so in case anyone finds this and would like to know how it was solved, this is the reply I got from hfried:

--------------------------------

Hi,

This is expected behaviour. A bit annoying sometimes, but not a bug.

Including isn't the same as textual insertion - each include is evalutated as a seperate template, so <% include Foo %> Is the same as $this->renderWith('Foo').

The result is that $Pos, $First, $Last etc won't work at the top level of an include (and neither will $Up, and $Top will refer to the loop member, not the page)

There is a work-around though, in that you can pass arguments into includes

-- Page.ss --
<% loop Foo %>
<% include Table TopPos=$Pos %>
<% end_loop %>

-- Table.ss --
$TopPos

Avatar
Xurk

Community Member, 50 Posts

20 August 2013 at 1:26am

Thanks for posting the answer, blueskies. That code is pretty awesome! :-)

Apparently, you can even pass along variables to the <% include %> from a different level within the template, e.g.:

<% include SomeOtherTemplate VarName=$Top.VarToSend %>

Avatar
blueskies

Community Member, 42 Posts

23 October 2013 at 1:01am

Ok, so a sequel to the problem: this is no longer an issue in 3.1. While upgrading to 3.1 I had to change everything back again to the way it was in 2.*.

So using:
<% loop Foo %>
<% include Table %>
<% end_loop %>

And inside "Table.ss" I can just use $First, or $even or whatever and it will be the $First or $Even from the loop Foo.

Go figure....

Avatar
Xurk

Community Member, 50 Posts

23 October 2013 at 1:03am

That sounds great blueskies! We've just adopted 3.1 for our latest project so I'll give it a try soon. It'll sure save a lot of hassle...