Liquid and other templating engines

Updated on 20-October-2016 at 10:16 AM

Business Catalyst End of life announcement - find out more details.

When enabling liquid on your site , you may already have code on your site (or add it lated) that conflicts with the newly introduced language.

For example, if in your templates you're already having things wrapped in double curly braces (ex: {{something}}) or when having code in you site that in liquid are considered as block delimiters (such as {%, %}, etc), once you enable liquid, the liquid engine will try to interpret it and this can produce unexpected results.

Also, some javascript libraries such as angular.js , handlebars or moustache can use in their template engine the same delimiters as liquid which can conflict with the ones in liquid.

If you are using angular.js , handlebars , moustache or any other javascript library that uses the double curly braces as a variable delimiter you will need to take extra precautions to make sure the Liquid ending does not attempt to interpret those variables.

For example, let's take the Angular.js code snippet below:

<div ng-app="">

<p>Name: <input type="text" ng-model="name"></p>
<p>You wrote: {{ name }}</p> 

</div>

On a page without Liquid enabled {{ name }} will be left as is and will be interpreted by Angular. After you enable the Liquid rendering engine, {{ name }} will be treated as a Liquid variable because it is wrapped in double curly braces and Liquid "executes" before any other templating engines you may use.

Depending where the code snippet is placed it may or may not work as expected, here is why:

  • if the code snippet is inserted on a regular webpage it will work. We do not have any Liquid tag named "name" on webpages (assuming you do not declare your own variable named name), the Liquid engine will try to interpret the tag and because it cannot it will render the tag in plain text as {{ name }}. When Angular is initialized it finds the code block as expected and processes it as expected
  • if the code snippet is inserted on the Online shop overall layout (or any other layout) where we already have a variable named name, Liquid will interpret and replace {{ name }} with the catalog name and will transform the code snippet into:
    <div ng-app="">
    
    <p>Name: <input type="text" ng-model="name"></p>
    <p>You wrote: Men's T-Shirts</p> 
    
    </div>

    When Angular is initialized and goes over the code block it cannot find the name variable any more.

There are two possible solutions to avoid this type of conflict.

Change your custom template engine's default delimiters

One approach to solving this conflict would be to change the delimiters so the variables are not interpreted at all by Liquid.

The procedure might differ depending on the templating engine you are using, here is how to change the default delimiter for Angular from double curly braces to something else.

For Mustache take a look at this Stackoverflow article , for Handlebar take a look at this article .

Escape conflicting templating engine markup using the Liquid tag

Another way to solve these types of issues would be to escape all the markup used by Angular (or your other templating engine) using the Liquid raw tag:


{%raw-%}
<div ng-app="">

<p>Name: <input type="text" ng-model="name"></p>
<p>You wrote: {{ name }}</p> 

</div>
{%endraw-%}

or:


<div ng-app="">

<p>Name: <input type="text" ng-model="name"></p>
<p>You wrote: {%raw-%}{{ name }}{%endraw-%}</p> 

</div>

The two code snippets above will work, in the first we wrap the entire snippet in the raw tag, in the second one we only wrap the variable we need to escape. Both approaches work.