Search code examples
ajaxsymfonytwigtemplate-inheritance

Symfony2 - How to implement partial / full templates for loading AJAX content in twig?


In my Symfony2/twig webapp I have a twig template, that only contains a <div id="#container">...</div>, no <html></html> wrapping. I use this for an ajax call where I embed this into my page layout. Let's call this layout ajax_template.html.twig.

<h1>Headline</h1>
{% block my_content %}
    <p>My content</p>
{% endblock %}

Now I have another template, that shall extend the ajax_template.html.twig. But this page is not called via ajax, but directly. So it shall also extend my base_layout.html.twig, where all the <html></html> wrapping is included. Should be something like:

# won't work because no multiple inheritance supported
{% extends 'MyBundle::base_layout.html.twig' %}
{% extends 'MyBundle:MyController:ajax_template.html.twig' %}

{% block my_content %}
    <p>My modified content</p>
{% endblock %}

Already tried a couple of methods, e.g. include() or use() in my twig templates. I also had a check, if the current path is an ajax call:

{% if '/ajax/' in path(app.request.attributes.get('_route')) %}
    {% extends 'MyBundle::base_layout.html.twig' %}
{% endif %}

But none of my approaches work. Do you have any ideas?


Solution

  • Richard Miller wrote a nice article that shows a good way to implement partial templates for AJAX-use.

    The article is called "Symfony2: Ajax and Full Page Templates".

    Lateron he published a second - more detailed - article that additionally covers my suggestions called "More on AJAX templates".

    These two articles (especially the second one) provide detailed implementation examples of what you're trying to do here.


    Basically the trick is to determine the template to extend from a variable as you can't wrap ...

    {% extends '..' %} 
    

    ... with a surrounding {% if %}-statement.


    working example

    {% set template = 'MyBundle::base_layout.html.twig' %}
    
    {% if '/ajax/' in path(app.request.attributes.get('_route')) %}
        {% set template = 'MyBundle:MyController:ajax_template.html.twig' %}
    {% endif %}
    
    {% extends template %}
    

    Please note that a solution involving a twig extension (as described in the above mentioned articles) is re-usable and generally a better practice.