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() and Object iteration in Template


Reply


4 Posts   925 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: [url]http://jqueryui.com/demos/accordion/[/url])

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?