DooPHP IRC channel


sub template

This is for general DooPHP discussion. Ask your questions here.

sub template

Postby ximian » Mon Feb 22, 2010 11:09 pm

Hi all,

I have a question about a template rendering process and how to do it.
Imagine i have main.html and on this template i have a for loop to cycle things.
Code: Select all
 some content
{% for genericArray as element %}
      {{ GENERIC }}
{% endfor %}
other content


Now, imagine i have 20 components classes that must cycle their arrays but i just want to be able to use ONE design of the cycle and inside the cycle i should be able to customize the element rendering. This way when designer changes main.html will change everything!

Note that, each component must be able to define how a element is rendered! This is important!
Let me try to explain what i want to archieve with and example (that do not works but explains my goal)

Imagine component A:
Code: Select all
$data = $this->....();
$this->view()->assign( 'GENERIC', '<strong>{{element.id}}</strong>' );
$this->view()->render( 'main', $data );

will be rendered as:
Code: Select all
 some content
{% for genericArray as element %}
      <strong>{{element.id}}</strong>
{% endfor %}
other content

so will output:
Code: Select all
 some content
      <strong>1</strong>
      <strong>2</strong>
other content



Imagine component B:
Code: Select all
$data = $this->....();
$this->view()->assign( 'GENERIC', '<a href="{{element.url}}" />' );
$this->view()->render( 'main', $data );

will be rendered as:
Code: Select all
 some content
{% for genericArray as element %}
      <a href="{{element.url}}" />
{% endfor %}
other content

will output:
Code: Select all
 some content
      <a href="http://...../a/" />
      <a href="http://...../b/" />
other content



How can i do it? Maybe with a new DooViewBasic method?

Francisco A
ximian
 
Posts: 143
Joined: Wed Nov 25, 2009 1:51 am
Location: Portugal

Re: sub template

Postby ximian » Wed Feb 24, 2010 5:52 pm

Anyone?
ximian
 
Posts: 143
Joined: Wed Nov 25, 2009 1:51 am
Location: Portugal

Re: sub template

Postby chucka » Wed Feb 24, 2010 8:14 pm

I use DooViewBasic, so this will be focused around that, yet I don't think DooView is missing any of these features.

To get this straight, you are looking to be able to give the same template different data and have it format it correctly right? If so you'll need to either check your data to see what it is each loop or you'll have to format it before it hits the view so you output the proper data in a simple loop. Either way, you will be checking and formatting your data, either in the controller or the view.

Example in view:
Code: Select all
some content
{% for genericArray as element %}
      {% if element.genericType = 1 %}
            <strong>{{element.content}}</strong>
      {% elseif element.genericType = 2 %}
            <a href={{element.location}}>{{element.content}}</a>
      {% endif %}
{% endfor %}
other content


I feel I might still be a little lost as to what you are trying to do so here is another solution you might try but be aware, I'm not sure if this works. Could see it being quite useful if it does though. As you are building your genericArray, set a 'view' variable (or something similar) for each element. Then, in your loop, call the required template of the same name set in the code to style that iteration of your loop. You'll need views for each style so for your request, we'll use 'linked' and 'unlinked' as your included views.

linked.html view:
Code: Select all
<a href="{{element.location}}">{{element.content}}</a>


unlinked.html view:
Code: Select all
<strong>{{element.content}}</strong>


For loop in your main.html:
Code: Select all
some content
{% for genericArray as element %}
      {% include '{{element.view}}' %}
{% endfor %}
other content
Image
chucka
 
Posts: 101
Joined: Tue Oct 06, 2009 7:39 pm

Re: sub template

Postby ximian » Wed Feb 24, 2010 11:32 pm

I found a way.

{% include .. %} will not work because if you have a segment inside that file and another segment outside, php will fail and die with an error, eg, imagine if you have a snippetA.html:
Code: Select all
 some content
{% if something %}

and snippetB.html:
Code: Select all
{% endif %}
 some end content

defined on main.html:
Code: Select all
Master content
{%include snippetA %}
other content
{% include snippetB %}

This will not work because php cannot understand snippetA.php because it has a not closed cycle.

I get this working by creating a new simple block called insert. This works like include except that instead of returning a filename to include, it statically includes its content in rendered component file:
Code: Select all
protected function block_include($params) {
   ...
   return "<?php include '{$cfilename}'; ?>";
}


Code: Select all
protected function block_insert($params) {
   ...
   return file_get_contents($cfilename);
}


Then to make my example work i just need to define 'insert' tag where i want my custom component rendering:
Code: Select all
some content
{% for genericArray as element %}
      {{insert custom}}
{% endfor %}
other content

and just define this template to use on a component:
Code: Select all
//componentA
$this->view()->render( 'main', array( 'genericArray' => $g, 'custom' => '/componentA' );

Code: Select all
//componentB
$this->view()->render( 'main', array( 'genericArray' => $g, 'custom' => '/componentB' );

and voila.

What do you think about this new tag? Very useful for me :)

Francisco A
ximian
 
Posts: 143
Joined: Wed Nov 25, 2009 1:51 am
Location: Portugal

Re: sub template

Postby RichardM » Sat Feb 27, 2010 11:41 am

Hi,

Will look at adding in support for this tag later today for use with render, renderLayout and renderRecursive (so you can use which ever you want and get the same behaviour of the parent).

However I would not recommend putting 2 parts of a logic statement into 2 separate files as it seems like your suggestion made. E.g. Start if statement in FileA and endif in FileB. This will become a pain to maintain in the future. If however you mean you want something more like: FileA.html
Code: Select all
{% if a == b %}
{% insert '1' %}
{% else %}
{% insert '2' %}
{% endif %}

Then I could see the benefit but just don't see how it would be useful any other way?

Richard
Note: code samples my not be 100% accurate.
RichardM
 
Posts: 1329
Joined: Sun Aug 30, 2009 6:03 pm
Location: Cumbria, UK

Re: sub template

Postby ximian » Sat Feb 27, 2010 1:19 pm

That is how i use it. With 'insert' tag i don't need to put logic in 2 files.. i can make the reverse: create one file for logic and 'insert' just the design parts :) That's why 'insert' tag is so important.

RichardM wrote:Will look at adding in support for this tag later today for use with render, renderLayout and renderRecursive

That's great. Thks.

Francisco A
ximian
 
Posts: 143
Joined: Wed Nov 25, 2009 1:51 am
Location: Portugal

Re: sub template

Postby ximian » Sat Feb 27, 2010 1:24 pm

Btw, can you add cycle tag too?

Francisco
ximian
 
Posts: 143
Joined: Wed Nov 25, 2009 1:51 am
Location: Portugal

Re: sub template

Postby RichardM » Sat Feb 27, 2010 1:56 pm

I will see what I can do...looking at adding support for setting 'pre' and 'post' markup so for example with the cycle it would put the array assignment at the start of the template file. So it's assignment would not be copied into for loops. Or would you want to do something like
Code: Select all
{% for a as b %}
{% for b->x as y %}
{% cycle [b->a] %}
{% endfor %}
{% endfor %}


whereby cycle variables would be defined from within the loop. Saying that from what I recall you suggesting as code this would not be possible anyway as the array would already have been assigned and should not be reset...I'll have to look into it a little later.

Richard
Note: code samples my not be 100% accurate.
RichardM
 
Posts: 1329
Joined: Sun Aug 30, 2009 6:03 pm
Location: Cumbria, UK

Re: sub template

Postby ximian » Sat Feb 27, 2010 2:21 pm

Richard, cycle is just a very simple tag that accepts an array and print consecutive value each time is executed (so it only makes sense if defined inside a loop, otherwise will only output the first value).

Code: Select all
{% for table as row .. %}
<tr bgcolor="{% cycle ['#eeeeee','#d0d0d0'] %}">
   <td>{{row.id}}</td>
</tr>
{% endfor %}


rendered as:

on top php compiled file
Code: Select all
<?php // assign global variable and define internal pointer to last element
      $data['doo']['cycle']['cid']=array('#eeeeee','#d0d0d0');end($data['doo']['cycle']['cid']);
?>

then, on cycle block definition:
Code: Select all
<?php // print next element. if next element is last point to first so that cycle can work next time
      if( next( $data['doo']['cycle']['cid'] ) == false ) print reset($data['doo']['cycle']['cid']);
      else print current($data['doo']['cycle']['cid']);
?>


Just that.

Francisco A
ximian
 
Posts: 143
Joined: Wed Nov 25, 2009 1:51 am
Location: Portugal

Re: sub template

Postby ximian » Sun Feb 28, 2010 10:43 pm

Richard, thanks for insert tag and cycle tag.

Cycle tag works great.
Insert tag has 2 problems:

on line 829:
Code: Select all
return array('false',

should be
Code: Select all
return array(false,


on line 789:
Code: Select all
$vfilename = str_replace('\\', '/', "{$this->rootViewPath}/$file.html");

should be:

Code: Select all
if (file_exists("{$this->rootViewPath}/{$file}.html")) {
  $vfilename = "{$this->rootViewPath}/{$file}.html";
} else {
  $vfilename = "{$this->defaultRootViewPath}/{$file}.html";
}


Francisco A
ximian
 
Posts: 143
Joined: Wed Nov 25, 2009 1:51 am
Location: Portugal

Next

Return to General Discussion

Who is online

Users browsing this forum: No registered users and 0 guests

cron