Jump to content

Multiple views for templates


mindplay.dk

Recommended Posts

Possibly what makes the most sense, is to just pass one variable? The developer can pass an array or a single string, or an object, e.g. for strongly typed view-models if wanted. If you did want to pass an array and have it extracted as local variables, all you'd have to do is call extract($data) in your child-template - it's not a lot of work...

  • Like 2
Link to comment
Share on other sites

Possibly what makes the most sense, is to just pass one variable? The developer can pass an array or a single string, or an object, e.g. for strongly typed view-models if wanted. If you did want to pass an array and have it extracted as local variables, all you'd have to do is call extract($data) in your child-template - it's not a lot of work...

I think this makes sense. Only issue is the template needs to be aware of that context, rather than just having a $var present like others are. But I think it's probably the right balance. 

Link to comment
Share on other sites

Templates need to be aware of context either way - this way, you can actually do a simple check to see if a context was provided at all: isset($data) - plus it makes it easier to pass the entire context on to another child-template.

Link to comment
Share on other sites

  • 2 weeks later...

I added this to the dev branch last week, so that you can now pass additional things to $page->render():

https://github.com/ryancramerdesign/ProcessWire/blob/dev/wire/modules/PageRender.module#L212

One of the things I wasn't thinking about before is that $page->render() was already capable of accepting an array of options (though not commonly used, mostly internal). So we weren't starting from a blank slate, and had to make something that was compatible and complimentary to what was already there. In terms of API calls, you can now do any of these:

$page->render($filename); // $filename assumed in /site/templates/
$page->render($pathname); // $pathname is full path, but must resolve somewhere in web root
$page->render($options); // array of options and/or your own variables
$page->render(array('foo' => 'bar')); // same as above
$page->render($filename, $options); // specify filename and options/vars, etc.

The $options variable was already something that $page->render() accepted before. Only it was used to specify some little-used modifiers to render(). Those are still there (and they are necessary), but now the utility of $options has been extended. When you want to specify options (outlined in the link above) you only need to specify the ones you want to change from the defaults (of course). Typically you don't need to change them, so I'm guessing that most would use $options to specify their own variables. 

Every rendered template now receives a copy of that $options array locally scoped. That $options array contains any variables you passed to $page->render(). It also contains PW's default options, should you want to examine any of them.

If you made this render() call:

echo $page->render('myfile.php', array('foo' => 'bar')); 

myfile.php could access the 'foo' variable like this:

echo $options['foo']; // outputs "bar"

One other addition that I'm thinking people might like is $options['pageStack']. That is an array containing a stack of pages that called render(). So if you are doing any recursive rendering of pages, any template can access $options['pageStack'] to see what page is rendering it, and any others before it. Previously this was not possible, and the only way a template could tell what other page was rendering it (if any) was for that renderer to tell the renderee, via $mypage->caller = $page; or something like that. 

  • Like 17
Link to comment
Share on other sites

Sounds good - though I am somewhat concerned about the reserved keys in $options, but I guess that's inevitable since they're already in use. They should probably be documented in the API, so that people don't accidentally overwrite reserved values. EDIT: you did already document them :)

  • Like 1
Link to comment
Share on other sites

  • 3 weeks later...

If you made this render() call:

echo $page->render('myfile.php', array('foo' => 'bar')); 

myfile.php could access the 'foo' variable like this:

echo $options['foo']; // outputs "bar"

Why is the variable handling not the same as with the TemplateFile class?

$tplf->setArray(array('foo' => 'bar')); 

and in the template I am able to access foo with:

 echo $foo; 
Link to comment
Share on other sites

Why is the variable handling not the same as with the TemplateFile class?

With template files you generally have a documented set of API variables ($page, $pages, $user, etc.), and this is what the set() methods of TemplateFile are geared towards. On the other hand, when passing variables into a $page->render(), variables passed in may be unknown/undocumented to the template file, and will be installation-specific, since PW doesn't pass in API variables that way. By having them in a known array ($options), you have a way of inspecting them, or at least knowing where they will be. Otherwise, the template file would have no means of self discovery for these things. It decreases the unknowns, increases the portability, and introduces an appropriate level of separation from the system API variables. On the other hand, this is largely theoretical… I've never had the need to pass in variables to template files in this manner, so am mainly just trying to accommodate the needs brought up in this thread. 

  • Like 2
Link to comment
Share on other sites

  • 4 weeks later...

Ryan, yes, I kind of missed the point. Since with TemplateFile class the actual template files is not automatically connected to the template itself which makes it necessary to pass certain variables if you want to use it like in this $page->render() context.

So now I got how powerful it actually is to use context sensitive templates, and you can totally automate this too.

Prefix your template files with contexts like:

  • team-member.php
  • home-team-member.php
  • sidebar-team-member.php

and use it like:

$child->render($page->template . '-team-member.php');

If the template is called when being the actual page, render() is called automatically, so it's loaded the unprefixed team-member.php then.

Awesome stuff.

  • Like 2
Link to comment
Share on other sites

  • 2 weeks later...
  • 2 weeks later...

This is great btw, been rewriting the previous template/view setup I was using to incorporate these changes.

The only issue I'm having right now is if I am rendering a partial template with a defined template filename argument TemplateFile.php is still checking & throwing an exception if isn't a file present in the base template folder.

For example if I have something like this in a template 

    
foreach($packages as $package)
{ 
echo $package->render('markup/layouts/package.php', array('layout' => 'package')); 
} 

I have to have a empty placeholder /site/templates/package.php file to avoid an exception. I dunno if that is as intended or it is still just checking for the default template file and trying to ensure that's there.

Link to comment
Share on other sites

If you are telling it to render using a specific template file, and that file doesn't exist, than an exception would be the right behavior. If there's a possibility the template might not be there, you should check yourself before asking it to render. Example:

$file = 'markup/layouts/package.php';
if(is_file(wire('config')->paths->templates . $file)) {
  echo $package->render($file, array('layout' => 'package')); 
} 
Link to comment
Share on other sites

  • 3 weeks later...

Hi guys,

i was reading this thread and remind me something i have tried to do many months ago:

http://processwire.com/talk/topic/2280-change-template-file-of-a-single-page/

http://processwire.com/talk/topic/2339-module-test-views/?hl=%2Bproof+%2Bconcept

I think that we are all looking the same objective but in different ways, so i read that the "render()" method handles in a more cleaner way the change of the file that render the page but i don't know how to use it in a module, because i would manage that views directly from the admin.

I hope i have explained well....

USSliberty

Link to comment
Share on other sites

I think that we are all looking the same objective but in different ways, so i read that the "render()" method handles in a more cleaner way the change of the file that render the page but i don't know how to use it in a module, because i would manage that views directly from the admin.

Not sure I understand the question. For the most part, ProcessWire's API works the same no matter where you use it from (whether a template or a module, etc). If you'd like, post a code sample of what's not working?

Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...