Jump to:

3444 Posts in 1030 Topics by 871 members

Template Questions

SilverStripe Forums » Template Questions » renderWith() and Object iteration in Template

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

Page: 1
Go to End
Author Topic: 883 Views
  • jdi
    Avatar
    Community Member
    34 Posts

    renderWith() and Object iteration in Template Link to this post

    Hey crew,

    This question will be exposing some serious holes in my knowledge of programming. But here we go:

    I have a custom class that extends Veiwable data and has a forTemplate() method to render the class.

    Question 1: When I iterate through my set of these classes in a template, what is the best method to reference the Objects (of my class) so that it renders with my Template?

    Question 2: What is the best Data type to reference my set as? At the moment I'm using DataObjectSet

    Examples:

    Class MyData.php:

    class MyData extends ViewableData {

    . . .

       function forTemplate() {
          return $this->renderWith(array(
             $this->class,
             'MyData'
          ));
       }

    . . .

    }

    Class Page_Controller:

    . . .

    function getMyDataSet() {
       return new DataObjectSet($myDataInstances);
    }

    . . .

    Page Template:

    <% control MyDataSet %>

       errr... what do I reference my Object and render it with it's template via?

    <% end_control %>

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

    My current solution is to do something like this:

    Class MyData.php:

    class MyData extends ViewableData {

    . . .

       function getDataRenderedWithTemplate() {
          return $this;   
       }

    . . .

    }

    Page Template:

    <% control MyDataSet %>

       $DataRenderedWithTemplate

    <% end_control %>

  • juergr
    Avatar
    Community Member
    17 Posts

    Re: renderWith() and Object iteration in Template Link to this post

    Hey jdi!

    I don't know if i understand your question right, but i've solved quit the same problem just a few days ago. But it seems to me that you have to write a new class, which just handles the rendering of your DataObject, so you dont have to write for each object a "renderWithSpecialTemplate"-function.

    What if've wanted to do: Create a simple class to generate jQuery Accordion elements (see: http://jqueryui.com/demos/accordion/)

    So basicaly i've created a class which holds a whole Accordion and another class which holds a single Accordion Item.
    Lets start with the Accordion class:

    class Accordion extends UIElement {
    private $items; // DataObjectSet with Accordion_item's
    private $item_template = 'Accordion_item';
    private $template = 'Accordion';
    private $ID;

    public function __construct($items, $name = null, $template = null, $itemTemplate = null) {
    $this->initialize($name);
    if($template != null) {
    $this->setTemplate($template);
    }
    if($itemTemplate != null) {
    $this->setItemTemplate($itemTemplate);
    }
    $this->setItems($items);
    }

    public function initialize($id = null) {
    if($id != null) {
    $this->ID = $id;
    } else {
    $this->ID = uniqid();
    }
    Requirements::css('mysite/UIComponents/accordion/css/accordion.css');
    $this->includeJQueryUI();
    Requirements::customScript(<<<JS
       $(function() {
    $( "#accordion_{$this->ID}" ).accordion({
    active: false,
    animated: false
    });
    });
    JS
    );
    }

    public function setItems($items) {
    $this->items = new DataObjectSet();
    foreach($items as $item) {
    $this->items->push(new Accordion_item($item,$this->item_template));
    }
    }

    public function setTemplate($template) {
    $this->template = $template;
    }

    public function setItemTemplate($template) {
    $this->item_template = $template;
    }

    public function forTemplate() {
    $data = array(
    'ID' => $this->ID
    );
    return $this->customise($data)->renderWith(array($this->template));
    }

    public function Items() {
    return $this->items;
    }
    }


    I think this code is pretty self explaining. Accordion extends UIElement which is a ViewableData-class with some basic function like including jQuery.

    Then we have the Items class (in the same file) which is straightforward and easy to understand:

    class Accordion_item extends ViewableData {
    private $data;
    private $template;

    public function __construct($item, $template) {
    $this->setData($item);
    $this->setTemplate($template);
    }

    public function setData($data) {
    $this->data = $data;
    }

    public function setTemplate($template) {
    $this->template = $template;
    }

    public function Item() {
    return $this->data->renderWith(array($this->template));
    }
    }

    Then there are two templates default templates.
    Accordion.ss

    <% if Items %>
    <div id="accordion_{$ID}">
    <% control Items %>
    $Item
    <% end_control %>
    </div>
    <% else %>
    <p>No entries found!</p>
    <% end_if %>

    Accordion_item.ss

    <h3><a href="#">$Title</a></h3>
    <div>
    $Content
    </div>

    And this is how to use it:

    $items = DataObject::get('Tour', 'StartDatum > NOW()', 'StartDatum ASC', '', $count);
    $UI = new Accordion($items, 'NextTouren');

    As a third and fourth argument of Accordion you can pass your own template. The second parameter is not required and defaults to a unique ID.

    My code is still under developement and there are several things which can be improved. So any hints and ideas are welcome!

    I hope this helps and have fun codding!

  • MarcusDalgren
    Avatar
    Community Member
    288 Posts

    Re: renderWith() and Object iteration in Template Link to this post

    Why are you extending ViewableData directly and not using DataObject?

  • juergr
    Avatar
    Community Member
    17 Posts

    Re: renderWith() and Object iteration in Template Link to this post

    Because I don't need the benefits of a DataObject such as storing any data in the DB or write/load from the DB. So i think its better to extend just ViewableData. All the displayed Data is passed to the Accordion class by passing a DataObjectSet to the constructor as first argument.

    What would the benefits be if I extend from DataObject?

    883 Views
Page: 1
Go to Top

Want to know more about the company that brought you SilverStripe? Then check out SilverStripe.com

Comments on this website? Please give feedback.