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!