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.

We've moved the forum!

Please use forum.silverstripe.org for any new questions (announcement).
The forum archive will stick around, but will be read only.

You can also use our Slack channel or StackOverflow to ask for help.
Check out our community overview for more options to contribute.

Template Questions /

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

Alternative to ChildrenOf(page-url) ?


Go to End


9 Posts   5581 Views

Avatar
ck_bullet

Community Member, 16 Posts

6 August 2010 at 4:19am

I have a holder template which has a controller that returns it's grandchildren. Inside the holder template I have a control block which loops through the returned list of grandchildren and spits out some information like title, etc. During each iteration I want to spit out each grandchild's siblings (including itself) and hide it inside a div which I will show onclick of a button. Initially using Top.ChildrenOf(page-url) seemed like what I needed, but I can't dynamically pass in the page-url argument during each loop pass. Anyone have any suggestions?

Avatar
inCharge

Community Member, 102 Posts

6 August 2010 at 8:50pm

Edited: 06/08/2010 8:52pm

I'm trying to do something similar.

In a nested control loop, how do you pass a parameter from the outer loop to the inner loop?

In this example, DatasetByParam is a place-holder for some function that returns a dataset based on a parameter e.g. sibling pages.

The problem is that the function receives the name of the variable (e.g. ID) instead of it's value (e.g. 43).

DatasetByParam is a member function of the Page class:

	public function DatasetByParam($id) {
		$Columns = array();

		$Columns[] = array( 'ID' => "Inside the function, ID=$id" );

		return new DataObjectSet($Columns);
	}

In Page.ss:

<% control Children %>
	Outside the function, ID=$ID<br/>

	<% control Top.DatasetByParam(ID) %>
		$ID<br/>
	<% end_control %>

<% end_control %>

The results:

Outside the function, ID=41
Inside the function, ID=ID
Outside the function, ID=42
Inside the function, ID=ID
Outside the function, ID=43
Inside the function, ID=ID

Avatar
inCharge

Community Member, 102 Posts

7 August 2010 at 4:33am

We can't pass a parameter to a control, because putting code/logic in the .ss file (i.e the view) would break the Model-View-Controller MVC design pattern. That's the wrong way to do it, but there is a right way.

The inner control loop is working in the context of (so has access to the functions & properties of) the object being iterated by the outer loop - in your case, the context for the inner loop is the grandchild page.

Therefore, if the Grandchild pages have a function that returns their siblings, you can use that for the inner loop.

<% control GrandChildren %>
<% control Siblings %>

...where the grandchild page class has a function like (I haven't tested this)

function Siblings() {
return DataObject::get('Page', "ParentID = $this->ParentId");
}

Or you could just add this to the Page class in Page.php and it would be inherited by all page types.

Avatar
ck_bullet

Community Member, 16 Posts

7 August 2010 at 5:35am

So I have <% control GrandChildren %> but inside this loop I cannot call any of the grandchild's controllers. For example inside the grandchild's class I have a controller called testOutput which merely returns a string, so within the control loop in the template I have $testOutput but I get nothing. I can't access any of the grandchild's controllers, any thoughts? Do I need to have any db relationship between the parent and grandchild?

Avatar
inCharge

Community Member, 102 Posts

7 August 2010 at 6:28am

Edited: 07/08/2010 6:31am

Does testOutput work if you use it on the GrandChild page i.e. GrandChild.ss?

The inner loop inside the GrandChildren control will behave as if it was on the GrandChild page itself, so If you put...

<% control GrandChildren %>
<% control Siblings %>

...on the grandparent page then the inner SIblings loop outputs the same as if you put...

<% control Siblings %>

on the GrandChild page itself. So you can test it like that, and break down the problem into smaller parts.

Can you use any of the other GrandChild properties inside the loop? e.g. Title, ID. If not then maybe GrandChildren isn't returning what you think it is. How is it defined?

Avatar
ck_bullet

Community Member, 16 Posts

10 August 2010 at 2:46am

Inside the inner loop I can access all its fields, just not the controller. On the grandchild template itself I can call the $testOutput controller, BUT I cannot use it within a control block. I have a Siblings controller inside the grandchild class which I loop through and I cannot call the $testOutput controller here. So on both the grandparent template and grandchild template I cannot access $testOutput inside a control block.

Avatar
inCharge

Community Member, 102 Posts

10 August 2010 at 3:18am

Am I right in thinking that the controller objects go in the Page class, rather than Page_Controller, because they are part of the data model, and not the concern of the controller. Does that make a difference?

Avatar
ck_bullet

Community Member, 16 Posts

10 August 2010 at 3:39am

Ahh, that made the difference. I removed the function from class MyClass_Controller {} and placed inside class MyClass {} and voila everything works now. Thanks so much Jules for walking me through the whole issue.

Go to Top