|
Smarty
WARNING: All discussion is moving to https://reddit.com/r/smarty, please go there! This forum will be closing soon. |
|
View previous topic :: View next topic |
Author |
Message |
Ben Gates Smarty Rookie
Joined: 31 Dec 2010 Posts: 7
|
Posted: Tue Mar 22, 2011 4:55 pm Post subject: [Smarty 3] Ajax & template inheritance |
|
|
Hello everybody !
I really love working with Smarty 3 and template inheritance, that's great !
However, I'd like to use some ajax apps that reload only one piece of my page. But I don't succeed to reach exactly what I need.
Have a look at my code :
MainTemplate.tpl :
Contains header, menu, footer.
Code: |
{block name='head'}
<title>My default Title</title>
{/block}
{block name='content'}
<div>My default content</div>
{/block}
|
ProductListing.tpl :
Contains my product listing, at the center of the page.
Code: |
{extends file='MainTemplate.tpl'}
{block name='head'}
<title>Product Listing</title>
{/block}
{block name='content'}
<div>
{foreach $Products AS $Product}
- {$Product.Name|stripslashes}
{/foreach}
...
</div>
{/block}
|
ProductListing.php :
Code: |
$smarty->assign('Products', $Products);
$smarty->display('ProductListing.tpl')
|
OK, works great ! ProductListing.php calls ProductListing.tpl who calls MainTemplate.tpl and I have a beautiful, full layout.
Well. Now, I'd like to reload only the content of my page.
I tried something like this :
Edit in ProductListing.tpl :
Code: |
{if !$Ajax}
{extends file='MainTemplate.tpl'}
{/if}
{block name='head'}
<title>Product Listing</title>
{/block}
{block name='content'}
<div>
{foreach $Products AS $Product}
- {$Product.Name|stripslashes}
{/foreach}
...
</div>
{/block}
|
ProductListing_Ajax.php is called by an Ajax event :
Code: |
$smarty->assign('Ajax', true);
$smarty->assign('Products', $Products);
$smarty->display('ProductListing.tpl')
|
so the output should be only the piece of code where my products are (I just need to reload what's in ProductListing.tpl and it should not have inheritance).
It just doesn't work
It looks like Smarty 3 doesn't allow "orphaned" templates. I want ProductListing_Ajax.php just to call ProductListing.tpl without rendering the whole template since it has been already rendered earlier.
You know what I mean to do ? Am I doing this wrong ? Or is there another way to reach the result I need ?
Thanks in advance,
Ben |
|
Back to top |
|
mohrt Administrator
Joined: 16 Apr 2003 Posts: 7368 Location: Lincoln Nebraska, USA
|
Posted: Tue Mar 22, 2011 5:06 pm Post subject: |
|
|
{extends ....} must be the first line of the template. You cannot conditionally extend a template. It would not make much sense to have {block} elements unless you are extending something, or being extended.
One way to solve: isolate the product template code that you want to replace with ajax, and put this into its own template and {include ...} into the extended template. Then when on an ajax call, you can call this template directly.
Another thing, I think you can dynamically extend:
{extend file=$foo}
So you could change the parent template on the fly. |
|
Back to top |
|
rodneyrehm Administrator
Joined: 30 Mar 2007 Posts: 674 Location: Germany, border to Switzerland
|
Posted: Tue Mar 22, 2011 5:50 pm Post subject: |
|
|
mohrt wrote: | One way to solve: isolate the product template code that you want to replace with ajax, and put this into its own template and {include ...} into the extended template. Then when on an ajax call, you can call this template directly. |
In some early applications I used a simple flag to determine if the header/footer/framework-stuff should be output along the actual content or not. This can be done with template inheritance as well. This might massively reduce the html the browser has to parse on arrival, as well as remove the <script>s you don't need to load (again).
Anyways, if you're working with jQuery, you can access the DOM of your ajax results. Have a closer look at jQuery.load(). Otherwise this little snippet may send you in the right direction as well:
Code: | $.get("/some/path/foo.html", function(data){
// have the html parsed
var $data = $('<div></div>').html(data);
// select what you need
var $content = $data.find('.your-selector-of-joy');
// throw it into your DOM
$content.appendTo( $( document.body ) );
}); |
mohrt wrote: | Another thing, I think you can dynamically extend:
{extend file=$foo}
So you could change the parent template on the fly. |
afair this will only work properly, if you include the $foo in your compile_id. Otherwise the template is compiled with a parent, and that one is being used regardless of what $foo says. |
|
Back to top |
|
Ben Gates Smarty Rookie
Joined: 31 Dec 2010 Posts: 7
|
Posted: Fri Mar 25, 2011 10:41 am Post subject: |
|
|
Hi guys,
Thanks for your replies.
The jquery method is not really good, because it renders the whole page before displaying just one part of it. That's not a good performance, especially for ajax applications. And I'm using Prototype. ^^
The {include file...} method is Smarty2-like, that's what I used before, and I think I'll go on using this way.
However, it would be REALLY great, for further versions of Smarty, to enable displaying just parts of child templates.
In my case, I'd have really enjoyed if I could do something like that :
$smarty->assign('Ajax', true);
$smarty->display('ProductListing.tpl', $extend=false, block='content'); for just rendering the 'content' block of my child template.
Don't you think so ?
Have a nice day !
Ben - a French Smarty fan |
|
Back to top |
|
rodneyrehm Administrator
Joined: 30 Mar 2007 Posts: 674 Location: Germany, border to Switzerland
|
Posted: Fri Mar 25, 2011 10:56 am Post subject: |
|
|
Ben Gates wrote: | The jquery method is not really good, because it renders the whole page before displaying just one part of it. That's not a good performance, especially for ajax applications. And I'm using Prototype. ^^ |
And where would you have gotten this false information from? both $.load and $.get result in the whole page being parsed to DOM, yes. Rendering only takes place after you inject the HTMLDocumentFragment into your document.
But yes, this approach still yields the overhead of parsing (and potentially loading resources therein) unnecessary content.
Ben Gates wrote: | The {include file...} method is Smarty2-like, that's what I used before, and I think I'll go on using this way. |
I don't see the reason for reverting to {include} for this. You may want to have a look at this, to get an idea of how to manipulate the extended template when doing template inheritance
Ben Gates wrote: | In my case, I'd have really enjoyed if I could do something like that :
$smarty->assign('Ajax', true);
$smarty->display('ProductListing.tpl', $extend=false, block='content'); for just rendering the 'content' block of my child template. |
We have been discussing a feature that should allow for this in one way or another. Don't know if we can push it into 3.1 - don't even know when 3.1 will come, really.
for the time being wrap everything in your extended template with {if !$ajax} that is NOT supposed to be displayed when in ajax-mode. That way your base template can hide everything but your {block "content"}. |
|
Back to top |
|
shital Smarty Rookie
Joined: 06 Nov 2012 Posts: 7
|
Posted: Thu Nov 08, 2012 7:17 am Post subject: |
|
|
i want to make my header and footer and vertical menu static...when i click on specific menu the content part should be loaded..but in my site the header , footer, menu these three parts get loaded...how can i make them static????
is this possible with ajax...???
if it is possible than how.....??? |
|
Back to top |
|
U.Tews Administrator
Joined: 22 Nov 2006 Posts: 5068 Location: Hamburg / Germany
|
|
Back to top |
|
shital Smarty Rookie
Joined: 06 Nov 2012 Posts: 7
|
Posted: Fri Nov 09, 2012 5:57 am Post subject: |
|
|
thank u Sir...one question more..that i want to fix header,footer and menu in my site..how can i do that in smarty????
i have already made my site..but now i want to fix header,footer and menu..i have included menu and header and footer in every tpl file...
so when i load any page every time header footer and menu will also load...
how can i fix them...??? |
|
Back to top |
|
bluejester Smarty Regular
Joined: 26 Apr 2012 Posts: 55
|
Posted: Mon Nov 26, 2012 3:42 pm Post subject: |
|
|
Hello everyone,
A few months afterwards I figured out the best way to work with Smarty 3 and Ajax with the same TPL, using Smarty Template Inheritance.
What makes the difference is the compile_id you will use to display() your tpl. With this compile id, you'll be able to specify if you want to render the whole page layout or just the piece of page you want to refresh.
Imagine your default page is a login form. You then have the whole layout, but when the user tries to log, you may either want to display a success message via Ajax if the user succeeds, or the same login form via Ajax + an error message if the user fails.
Create the main layout of your page :
MasterPage.tpl
Code: | <!doctype html>
<html>
<head>
{block 'Title'}
<title>Page title</title>
{/block}
{block 'MetaTags'}
<!-- Some Meta tags... -->
{/block}
{block 'CSS'}
<!-- Some CSS... -->
{/block}
{block 'JS'}
<!-- Some JS... -->
{/block}
</head>
<body>
<header>
{block 'Header'}
<!-- ... -->
{/block}
</header>
<nav>
{block 'Navigation'}
<!-- ... -->
{/block}
</nav>
<div id="Wrapper">
{block 'MainContent'}{/block}
</div>
</body>
</html> |
Now, the layout of an Ajax response (empty by default) :
AjaxResponse.tpl :
Code: | {block 'MainContent'}{/block} |
And, the Login form TPL :
Login.tpl
Code: | {extends $ParentTemplate}
{block 'MainContent'}
<div id="Login">
<form action="{$smarty.server.PHP_SELF}" method="POST">
<input type="hidden" name="Action" value="Login" />
User Name : <input type="text" name="UserName" /><br />
Password : <input type="password" />
<input type="submit" value="Log in" />
</form>
</div>
{/block} |
Finally, your PHP should look like this :
Page.php :
Code: | <?php
# Define is the user is using Ajax
define('IS_AJAX', (bool) (isset($_SERVER['HTTP_X_REQUESTED_WITH'])
&& !empty($_SERVER['HTTP_X_REQUESTED_WITH'])
&& strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest'));
# Include Smarty files
require 'Smarty/libs/Smarty.class.php';
# Instanciate Smarty
$Smarty = new Smarty();
$Smarty -> setTemplateDir('smarty_tpl');
$Smarty -> setCompileDir('smarty_compile');
# Smarty's compile Id will be "AjaxResponse" if the user uses Ajax, "MasterPage" otherwise
$Smarty -> setCompileId((bool) IS_AJAX ? 'AjaxResponse' : 'MasterPage');
# Your TPL's parent will be "AjaxResponse.tpl" if the user uses Ajax, "MasterPage.tpl" otherwise
$Smarty -> assign('ParentTemplate', $Smarty->compile_id . '.tpl');
# You will now render Login.tpl with the whole layout or just itself
$Smarty -> display('Login.tpl', null, $Smarty->compile_id); |
It just kicks ass
Enjoy !
Blue jester (formerly Ben Gates) |
|
Back to top |
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|
|