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.

Template Questions /

including dynamical Includes


Reply


7 Posts   1695 Views

Avatar
Silverfish

Community Member, 59 Posts

6 May 2011 at 2:34am

Hello Everybody,

in general, I would like to different include templates in different pages regarding to the top-menue page the current page is a child of. So if you have PA, PB and PC in TopNavi i want all pages under PA to <% include template_a %>, PB <% include template_b %>, etc.

My current approach is to have a GetTemplate() method in the page controller that returns the tempate name by checking the parent page id's. The problem in this is how to include the returned template.

<% include GetTemplate %> seems to do nothing and
<% include $GetTemplate %> displays exactly this line, at least containing the template name returned by GetTemplate().

Is there a possibility at all to include dynamically generated template names?
Or is the approach generally bad and tehre is another, better one?

Thanks a lot for any hint :)

SF

Avatar
Zauberfisch

Community Member, 30 Posts

6 May 2011 at 2:55am

Edited: 06/05/2011 2:55am

yay, another fish <3

The way you tried it is not possible.

<% include GetTemplate %> this will search for a template called GetTemplate.ss inside a Includes folder
<% include $GetTemplate %> this will be printed out because it isn't a valid ss template code

what you can do is:

1) do a lot of IF blocks to select the template you need

2) move your includes out of the includes folder into the Template folder and then do something like that:
I suggest you call your include files with a prefix, so you have like:
themes/myTheme/templates/Include_PA.ss
themes/myTheme/templates/Include_PB.ss
themes/myTheme/templates/Include_PC.ss

template:
$myIncludeThing

in the Include_PA.ss template:
<% control myTopMenuItems %>$Title ...<% end_control %>

php:

function myIncludeThing() {
$TopMenuItems = DataObject::get('Page', 'ShowInTopMenu = 1');
return $this->customize(array('myTopMenuItems' => $TopMenuItems))->renderWidth('Include_'.$this->GetTemplate());
}

NOTE: I coded that without IDE and never tested it, you probably have to fix some typos and small errors, but I think it points in the right direction.

Avatar
Silverfish

Community Member, 59 Posts

9 May 2011 at 9:50pm

Edited: 09/05/2011 9:51pm

Hmm....

Thanks for these two good workarounds. Anyway, I won't use none of them. The first one is just too many if blocks, getting even more complicated when you want to have a default template that gets included if none of the conditions fits. Since templates don't support a elseif condition this makes the thing even more ugly ;). Nevertheless I think this would be still the better solution.
The second one seems quite handy but results in a lot of redundant (template) code, what I always avoid at any cost.

What I did is writing a controller method that simply reads the required template and returns the code to the template.

public function DynInclude($filename = 'Default.ss')
{
   # isn't there a Sivlerstripe variable containing the current project location???
   $themes = dirname(dirname(dirname(__FILE__))) . '/themes/project/templates/Includes';
   $include = $themes . '/' . $filename;
   
   if ( ! is_readable($include) )
   {
      # todo: raise errror
      return false;
   }
      
   return file_get_contents($include);
}

Of course this approach isn't perfect neither, since template content doesn't get parsed by Silverstripe any more so you can't use any variables in the includes. But in my special case this isn't required.

Anyway, if just someone could help me out with the silverstripe var for the current project location, everything would be fine for now. ;)

Thx a lot
SF

Avatar
Zauberfisch

Community Member, 30 Posts

9 May 2011 at 11:00pm

Hello,

you will get the name of the project by calling "project()", in the normal case that is "mysite"

I hope that I don't tell you something wrong here, but I believe there is a else_if in template.

anyway, for the solution with renderWith() I don't quiet understand where that should bring redundant template code.

Avatar
Silverfish

Community Member, 59 Posts

12 May 2011 at 12:01am

Hi,

(don't know how to cite here)

> you will get the name of the project by calling "project()", in the normal case that is "mysite"
Thanks for this one, but i was looking for the path of the project within the filesystem (to avoid the several dirname(__FILE__)'s)

> I hope that I don't tell you something wrong here, but I believe there is a else_if in template.
After some research you're right! Had problems with if_else till today since it doesn't exactly work like expected (see http://www.silverstripe.org/template-questions/show/8210) (another fish there, btw ;))

> anyway, for the solution with renderWith() I don't quiet understand where that should bring redundant template code.
If i understood yor last idea correctly, Include_PA.ss, Include_PB.ss, Include_PC.ss (and the others) would look pretty similar, containing all html headers and all page container stuff. They would only differ in the area that I tried to include dynamically.

Chers
SF

Avatar
Silverfish

Community Member, 59 Posts

5 June 2011 at 3:53am

> you will get the name of the project by calling "project()", in the normal case that is "mysite"
Thanks for this one, but i was looking for the path of the project within the filesystem (to avoid the several dirname(__FILE__)'s)

Finally got it: Director::baseFolder()

Cheers
SF

Avatar
martimiz

Forum Moderator, 1133 Posts

23 July 2011 at 1:37am

Hi
Just getting back at ZauberFish' renderwith() example - there is no need to create lots of similar templates for the entire page. What you do is create the small different include templates you want, and then place

...
$myIncludeThing
...

in the appropriate location in your overall page template, or wherever you want it. This is in fact a very nice solution, I think :-)