Smarty Forum Index Smarty
WARNING: All discussion is moving to https://reddit.com/r/smarty, please go there! This forum will be closing soon.

[Smarty 3] Ajax & template inheritance

 
This forum is locked: you cannot post, reply to, or edit topics.   This topic is locked: you cannot edit posts or make replies.    Smarty Forum Index -> Tips and Tricks
View previous topic :: View next topic  
Author Message
Ben Gates
Smarty Rookie


Joined: 31 Dec 2010
Posts: 7

PostPosted: Tue Mar 22, 2011 4:55 pm    Post subject: [Smarty 3] Ajax & template inheritance Reply with quote

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 Sad
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
View user's profile Send private message
mohrt
Administrator


Joined: 16 Apr 2003
Posts: 7368
Location: Lincoln Nebraska, USA

PostPosted: Tue Mar 22, 2011 5:06 pm    Post subject: Reply with quote

{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
View user's profile Send private message Visit poster's website
rodneyrehm
Administrator


Joined: 30 Mar 2007
Posts: 674
Location: Germany, border to Switzerland

PostPosted: Tue Mar 22, 2011 5:50 pm    Post subject: Reply with quote

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
View user's profile Send private message Visit poster's website
Ben Gates
Smarty Rookie


Joined: 31 Dec 2010
Posts: 7

PostPosted: Fri Mar 25, 2011 10:41 am    Post subject: Reply with quote

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 ? Smile

Have a nice day !
Ben - a French Smarty fan Wink
Back to top
View user's profile Send private message
rodneyrehm
Administrator


Joined: 30 Mar 2007
Posts: 674
Location: Germany, border to Switzerland

PostPosted: Fri Mar 25, 2011 10:56 am    Post subject: Reply with quote

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
View user's profile Send private message Visit poster's website
shital
Smarty Rookie


Joined: 06 Nov 2012
Posts: 7

PostPosted: Thu Nov 08, 2012 7:17 am    Post subject: Reply with quote

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
View user's profile Send private message
U.Tews
Administrator


Joined: 22 Nov 2006
Posts: 5068
Location: Hamburg / Germany

PostPosted: Thu Nov 08, 2012 4:15 pm    Post subject: Reply with quote

Here is an article how Smarty and Ajax can work together http://www.ibm.com/developerworks/opensource/library/wa-aj-smarty/index.html

Or google for "Smarty ajax" you will find lots of articles and examples
Back to top
View user's profile Send private message
shital
Smarty Rookie


Joined: 06 Nov 2012
Posts: 7

PostPosted: Fri Nov 09, 2012 5:57 am    Post subject: Reply with quote

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
View user's profile Send private message
bluejester
Smarty Regular


Joined: 26 Apr 2012
Posts: 55

PostPosted: Mon Nov 26, 2012 3:42 pm    Post subject: Reply with quote

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 Smile
Enjoy !

Blue jester (formerly Ben Gates)
Back to top
View user's profile Send private message Visit poster's website
Display posts from previous:   
This forum is locked: you cannot post, reply to, or edit topics.   This topic is locked: you cannot edit posts or make replies.    Smarty Forum Index -> Tips and Tricks All times are GMT
Page 1 of 1

 
Jump to:  
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
Protected by Anti-Spam ACP