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 /

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

renderWith() and Object iteration in Template


Go to End
Reply


4 Posts   1187 Views

Avatar
jdi

Community Member, 34 Posts

15 January 2012 at 11:32pm

Edited: 15/01/2012 11:32pm

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 %>

Avatar
juergr

Community Member, 17 Posts

16 January 2012 at 12:57am

Edited: 16/01/2012 1:04am

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!

Avatar
MarcusDalgren

Community Member, 288 Posts

16 January 2012 at 3:51am

Why are you extending ViewableData directly and not using DataObject?

Avatar
juergr

Community Member, 17 Posts

16 January 2012 at 5:12am

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?