How to change the default delimiter of Handlebars.js?

15,635

Solution 1

This is not possible with "standard" Handlebars. https://github.com/wycats/handlebars.js/issues/227

Solution 2

Although it may be true that you can't configure Handlebars' expression delimiters, that's not the only way to resolve the conflict between Handlebars and Blade. Blade provides syntax that allows you to avoid the conflict by designating what should be passed on to Handlebars. (This is fitting, since Blade created the conflict to begin with, and it's necessary, since Blade is processing the template before Handlebars ever sees it.) Just prepend @ before the curly braces that you want Blade to ignore and pass as-is to Handlebars. Here's a very short snippet of a much larger example:

...
    <link
        rel="stylesheet"
        type="text/css"
        href="{{ asset("css/bootstrap.theme.3.0.0.css") }}"
    />
    <title>Laravel 4 Chat</title>
</head>
<body>
    <script type="text/x-handlebars">
        @{{outlet}}
    </script>
...

{{outlet}} will be passed to Handlebars, but {{ asset("css/bootstrap.theme.3.0.0.css") }} will be handled by Blade.

Solution 3

I created handlebars-delimiters on GitHub / npm to make it easy to use custom delims with Handlebars.

var Handlebars = require('handlebars');
var useDelims = require('handlebars-delimiters');

var a = Handlebars.compile('{{ name }}<%= name %>')({name: 'Jon'});
console.log(a);
//=> 'Jon<%= name %>'


// Pass your instance of Handlebars and define custom delimiters
useDelims(Handlebars, ['<%=', '%>']);
var b = Handlebars.compile('{{ name }}<%= name %>')({name: 'Jon'});
console.log(b);
//=> '{{ name }}Jon'

The idea for the compile function came from https://stackoverflow.com/a/19181804/1267639

Suggestions for improvement or pull requests are welcome!

Solution 4

I've made this function. Hope it can be useful for someone..

/**
* change the delimiter tags of Handlebars
* @author Francesco Delacqua
* @param string start a single character for the starting delimiter tag
* @param string end a single character for the ending delimiter tag
*/
Handlebars.setDelimiter = function(start,end){
    //save a reference to the original compile function
    if(!Handlebars.original_compile) Handlebars.original_compile = Handlebars.compile;

    Handlebars.compile = function(source){
        var s = "\\"+start,
            e = "\\"+end,
            RE = new RegExp('('+s+'{2,3})(.*?)('+e+'{2,3})','ig');

            replacedSource = source.replace(RE,function(match, startTags, text, endTags, offset, string){
                var startRE = new RegExp(s,'ig'), endRE = new RegExp(e,'ig');

                startTags = startTags.replace(startRE,'\{');
                endTags = endTags.replace(endRE,'\}');

                return startTags+text+endTags;
            });

        return Handlebars.original_compile(replacedSource);
    };
};

//EXAMPLE to change the delimiters to [:
Handlebars.setDelimiter('[',']');

Solution 5

Instead of changing the delimiters you can create files with your handlebars templates in without the .blade extension. Just include these files in your blade template. E.g

Blade Template File - template.blade.php

@extends('master.template')

@section('content')

    @include('handlebars-templates/some-template-name') 

@stop

some-template-name File - some-template-name.php

<script type="text/x-handlebars" data-template-name="content">
<div>
 <label>Name:</label>
 {{input type="text" value=name placeholder="Enter your name"}}
</div>
<div class="text">
<h1>My name is {{name}} and I want to learn Ember!</h1>
</div>
</script>
Share:
15,635

Related videos on Youtube

George D.
Author by

George D.

I love everything that has to do with Web Design/development.

Updated on June 04, 2022

Comments

  • George D.
    George D. almost 2 years

    I need to use handlebars.js and I also use Blade template engine from Laravel (PHP Framework). The tags {{}} conflict with blade's placeholders that are exactly the same.

    How can I change those {{var}} to something like <% var %> ?

    • George D.
      George D. over 11 years
      The workaround I did is to regex replace them with JS. I used this code -> var templatecontent = $("#template").html().replace(/<%/, '{{').replace(/%>/, '}}'); var template = Handlebars.compile(templatecontent);
    • George D.
      George D. over 11 years
      But its a workaround, not sure if its the right thing to do here.
  • Matt Ball
    Matt Ball over 11 years
    Sure, or store the templates outside of the HTML entirely, as suggested on GH: github.com/wycats/handlebars.js/issues/227#issuecomment-9950‌​931
  • George D.
    George D. over 10 years
    The trick you are saying is on laravel 4.1 ? Let me know about the version please.
  • samuraiseoul
    samuraiseoul about 10 years
    Beautiful! Works for me! Thanks so much!
  • MortalViews
    MortalViews about 10 years
    This should be the accepted answer, and its not a trick,, but a proper solution.
  • Christian Michael
    Christian Michael almost 10 years
    What about triple curly braces? Currently Blade Template doesn't offer @{{{var}}}
  • lud
    lud almost 10 years
    @Christian hmmm you will need to escape the text yourself @{{ e($var) }}
  • Christian Michael
    Christian Michael almost 10 years
    @niahoo handlebars currently has this {{{var}}} for unescaped value / expression. Is this what you're suggesting? @{{ e('{var}') }} ?
  • lud
    lud almost 10 years
    @ChristianMichael e() is a PHP function which does escaping. I was wrong, we must escape before then print with double braces, I don't know how to do. Best may be this forumsarchive.laravel.io/viewtopic.php?id=1451
  • itsjavi
    itsjavi almost 10 years
    nice approach I will use it that way
  • Ander Biguri
    Ander Biguri over 9 years
    While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes.
  • Stefan
    Stefan over 9 years
    @AnderBiguri: how is this a link? ;-)
  • Ander Biguri
    Ander Biguri over 9 years
    @Stefan Sorry, it gets "autowritteng" while moderating. The point is, there is no explanation in this answer. Just gives an answer, but not explaining why or why not.
  • Stefan
    Stefan over 9 years
    @AnderBiguri: agreed.
  • littlegreen
    littlegreen over 9 years
    This is nice, but often I want to put Blade tags within my Handlebars templates and then it's not handy.
  • Kevin Campion
    Kevin Campion almost 9 years
    It seems not working with Handlebars v3.0.3. I created a new answer based with your source code, and it works now. Thank you!
  • mikemaccana
    mikemaccana over 8 years
    +1 making real libraries, putting them on GitHub where we can send PRs and file issues, and publishing them on npm rather than having people copy paste the same solutions from StackOverflow.
  • Mark Lester
    Mark Lester almost 4 years
    there are 3 principal layers of potential template execution imo. On first execution, essentially on a domain/language, at server delivery (good old CGI time) and in the client. I am using {% {@ and {{ respectively. I am also using {"some text"} as effectively shorthand for {%__ "some text"%}, meaning call the __ helper to translate "some text" at first exec . All of these are facilitated by this. thx