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 /

renderWith() makes navigation disappear


Go to End
Reply


10 Posts   8363 Views

Avatar
schellmax

Community Member, 126 Posts

16 January 2009 at 3:41am

hello,
i'm trying to render a page through the action of another pages controller like so:

function showPage {
   $page = DataObject::get_by_id('Page',7);
   return $page->renderWith('Page');
}


when i visit the url (somepage/showPage), page with id 7 is rendered, but the navigation (using controls like Menu(2) etc) disappears.

i found a post concerning the same problem in the forum archives, but without any replies:
http://www.silverstripe.org/archive/show/160453

am i getting something wrong about renderWith()?

Avatar
dio5

Community Member, 501 Posts

17 January 2009 at 3:29am

Isn't renderWith() supposed to get an array of parameters?

so this would become:

$page->renderWith(array('MyPage', 'Page'));

Avatar
schellmax

Community Member, 126 Posts

17 January 2009 at 4:46am

thanks for the answer, but according to the docs both parameter types are allowed:
from http://doc.silverstripe.org/doku.php?id=templates&s=renderwith#calling_templates_from_php_code:

... $controller->renderWith("TemplateName"); ...

... renderWith() can also be passed an array of template names. If this is done, then renderWith() will use the first available template name. ...

strange enough, in my case the use of a single string doesn't do the trick, i have to pass an array like Array('ProjectPage', 'Page'), even though 'ProjectPage' is not a template but a layout (in the 'layouts' folder) to render a ProjectPage.

as for the missing navigation, i got it working again using the following instead of Menu(2):

<% control Parent.Children %>

not sure wheter it's a bug or my misunderstanding of renderWith - there's no overly detailed explanation on in this the docs...

Avatar
jam13

121 Posts

17 January 2009 at 4:57am

That's how it's supposed to work AFAIK. Normal rendering behavoir is to follow the class inheritance chain to get potential template names, but when you use renderWith it requires you to explicitly define the list of templates to try. So if you just use 'ProjectPage' then it finds that for the Layout template but when it fails to find a main template called ProjectPage it doesn't look for 'Page'.

Avatar
schellmax

Community Member, 126 Posts

17 January 2009 at 5:33am

oh i understand - thanks for pointing this out.
maybe there's also a reasonable explanation for the 'Menu(2)' not working?...

Avatar
simon_w

Forum Moderator, 474 Posts

17 January 2009 at 7:15am

Menu() is defined in the Controller class, so if you call renderWith() in your Page subclass, the method doesn't exist in a place where it can be called. If the method calling renderWith() is in your Controller, then Menu() should work.

Avatar
schellmax

Community Member, 126 Posts

19 January 2009 at 11:01pm

that's a good hint, but even though the method calling renderWith is in a class extending Page_Controller, none of my controller methods are available in the ProjectPage.ss layout??

i even have to call the init() function of PageProject_Controller before the renderWith statement to have the required js (via requirements::javascript) loaded.

here is the method i'm calling via url 'showproject/project/7' (inside showproject_controller):

   function project($action) {
      $projectPage = DataObject::get_by_id('ProjectPage', $action['ID']);
      ProjectPage_Controller::init(); //loads necessary js
      return $projectPage->renderWith(Array('ProjectPage','Page'));
   }


any further hints appreciated...

Avatar
ajshort

Community Member, 244 Posts

19 January 2009 at 11:32pm

Edited: 19/01/2009 11:36pm

This is the correct behaviour - you're calling renderWith() on your ProjectPage class, which is not attached to the controller by default, which means you can't access any of those methods.

Firstly - is there a reason you're using an action to render another page? It would be much simpler to directly link to the page. It seems that this is what you're currently trying to do, so I would reccomend just using the $Link method in your template and link directly to the page in order to avoid duplicate content + hack problems etc.

On the other hand, if the ProjectPage isn't a sub-class of SiteTree, it makes sense to render in an action. The best way to do this is to create a custom action template - you do this by making a template called (Class)_(action).ss - in this case PageProject_project.ss

You can then modify your project method to something like this:

public function project() {
   return array (
      'ProjectPage' => DataObject::get_by_id(...)
   );
}

You can then use <% control ProjectPage %> in your template.

If you are really stuck with using an action to render a SiteTree object, you can do something like this to couple it to a controller: (I'm presuming your using 2.2.x)

public function project() {
   $controller = new ProjectPage_Controller(DataObject::get_by_id('ProjectPage', ...));
   $controller->init();
   
   return $controller->getViewer('index')->process($controller);
}

Go to Top