D-L
D-L

Reputation: 255

SilverStripe 3.1.x How to Render a Page with a specific template from an Extension?

SilverStripe 3.1.x How to Render with a specific template from an Extension?

In SilverStripe 3.1.x, How can I make a Page render with a specific template from a Module Extension? I'm working on a module that allows an administrator to change the display behaviour of a page at specific timeframes. Making the page redirect works fine, but when it comes to rendering with a specific template, it seems to get ignored.

Here's an excerpt of the key parts of my code:

mymodule/_config/mymodule.yml

---
Name: mymodule
After:
- 'framework/*'
- 'cms/*'
---

Page_Controller:
  extensions:
    - MyPage_ControllerExtension

mymodule/code/MyPage_ControllerExtension.php

class MyPage_ControllerExtension extends Extension {

    public function onAfterInit() {

        //Render with MyTestTemplate.ss as a test
        return $this->owner->renderWith(array('MyTestTemplate', 'Page')); //Don't work

        //try redirecting
        //return $this->owner->redirect('http://google.com'); //Works fine 

    }

}

mysite/code/Page.php

class Page_Controller extends ContentController {

    private static $allowed_actions = array ();

    public function init() {
        parent::init();

    }

}

themes/simple/templates/Layout/MyTestTemplate.ss

<% include SideBar %>
<div class="content-container unit size3of4 lastUnit">
    <article>
        <h1>MY TEST TEMPLATE</h1>
        <div class="content">MY TEST CONTENT</div>
    </article>
</div>

After flushing the template cache, SilverStripe does not render Page.ss with MyTestTemplate. How do I achieve that from the MyPage_ControllerExtension above?

When I debug by adding the parameter ?showtemplate=1 to the URL, I can see that SilverStripe does indeed get the content for MyTestTemplate, but in the end, it ignores it and the Layout/Page.ss template gets used instead.

Upvotes: 0

Views: 2029

Answers (3)

D-L
D-L

Reputation: 255

So, the final solution, from @Martimiz, which works whether or not an action is called is:

In the Page_Controller class in mysite/code/Page.php, add the following property as follows:

class Page_Controller extends ContentController {
    public $templates;
    ⋮
}

In mymodule/code/MyPage_ControllerExtension.php, add:

class MyPage_ControllerExtension extends Extension {

    public function onAfterInit() {
        $action = $this->owner->request->param('Action');
        if(!$action) $action = 'index';

        $this->owner->templates[$action] = array('MyTestTemplate', 'Page');
    }

}

Upvotes: 0

Martimiz
Martimiz

Reputation: 28

This would work for actions and index functions when default rendering is used (by returning array() or $this)

public function onAfterInit() {
    $this->owner->templates['index'] = array('MyTestTemplate', 'Page');
}

You could also use $this->owner->templates['currentaction'] if you want

But you'd have to add the following property to your Page_Controller class, because although it is checked from within the Controller class, it doesn't seem to be defined anywhere in the class chain (?):

public $templates;

Upvotes: 1

Martimiz
Martimiz

Reputation: 28

You could use the index() function in your (Data)Extension to return the rendered data:

public function index() {
    return $this->owner->renderWith(array('MyTestTemplate', 'Page')); 
}

Note: that would fail though, if the Page you're extending already has an index() function defined.

Upvotes: 0

Related Questions