Symfony2: More on Twig Ajax Templates

This post is a few notes to follow up on some of the responses to my previous post on reusing inner Twig templates for full page responses and ajax responses.

One clarification to make, as I had not made it clear, is that is only relevant to the case where you are sending back HTML fragments is response to Ajax requests (and where that fragment is the same as the full page response minus the common parts of the page). If your Ajax response is XML or JSON then this technique is irrelevant as you will already be using different templates. In that case you can switch template using the _format route parameter or you may want to look at using the FOSRestBundle.

Thomas Rabaix of the Sonata Project pointed out that a further improvement can be made by separating out the names of the templates to be extended into configuration by using Twig globals. This means that the choice of template to extend is no longer hardcoded into the templates at all. In a Symfony2 app it is easy to register globals in config. Our simple intermediate template that decides whether to extend the full or ajax template would now look like this:

with the global parameters set in the app’s main config file:

I also mentioned moving any logic for deciding which template to use to a Twig extension, if it became more complex than our simple ternary operator, so that it could be tested outside of a template. This could return the template to use rather than just a boolean allowing more complex decisions to be made as well.

A simple version of the extension may look like this:

We can now remove the intermediate template altogether and call our twig function from the inner template:

In this example the templates are hardcoded in as class constants to keep the example straightforward, this could be changed to have them injected in to the extension so that they can be kept in configuration instead.

Symfony2: Ajax and Full Page Templates

A quick look at one way to use the same controller action and Twig template (or just template) for displaying a full page and also just the inner content for an Ajax request in a Symfony2 application. This is using the ability to set which template a twig template extends from dynamically (which is shown here in the Twig documentation).

So assuming we have a current inner template that looks like this:

This extends our main layout template that adds the rest of the page, the header, footer etc. Whenever we render it we will get the full page with all the content from the outer template as well. For an Ajax request we only want the content of the body block to be displayed, we do not want any of the outer content that is provided by the the main template and we are not interested in the title block either. We can do this by creating an alternative Ajax outer template to render just the body block that is as simple as:

Then in our inner template we can use the app global to find out if it is an Ajax request:

Note: If you are using Twig outside of Symfony2 then you will need to add an alternative way of identifying whether it is an Ajax request.

It’s a simple as that. However we can add an improvement in order to avoid having to repeat that check in multiple inner templates. By adding an intermediate template that contains just that logic and extending the inner template from it this can be kept in a single template:

Another possible time you may need this sort of solution is where a template should sometimes be rendered as a main request and sometimes as a subrequest. The only real difference here is the logic in checking which template to extend. By passing a parameter when rendering a subrequest you can then check that:

If you needed to combine these and other reasons for making the decision it would be worth moving the logic involved to a function using a Twig extension where it could then be tested outside of the template.