Search code examples
javascripttemplate-enginedust.jstypeahead.js

What's the least intrusive way to make dust.js able to render typeahead.js templates?


typeahead.js gives us the ability to render templates for our autocomplete suggestions using our engine of choice as long as the engine implements this API:

// engine has a compile function that returns a compiled template
var compiledTemplate = ENGINE.compile(template);

// compiled template has a render function that returns the rendered template
// render function expects the context to be first argument passed to it
var html = compiledTemplate.render(context);

Now dust.js has a slightly different take on the matter:

var compiled = dust.compile("Hello {name}!", "intro");
dust.loadSource(compiled);

Since I have dust.js already integrated, I'd like to use it to render typeahead's suggestions, too. I can probably wrap dust's engine object and provide the API required, but I'm wondering if there's a less intrusive and/or more elegant way to do this, e.g. by dynamically attaching the required functions to the dust object itself?

Edited to add: mixing what @user2103008 and @Simon have, here's what I'm using with typeahead-0.9.3:

function typeaheadFakeCompile(dustTemplateName) {
    return function(data) {
        var html;
        dust.render(dustTemplateName, data, function(err, out) { html = out; })
        return html;
    }
}

var compiled = dust.compile('Hello {name}!', 'myTemplate');
dust.loadSource(compiled);

$('selector').typeahead({
   template: typeaheadFakeCompile('myTemplate')
)};

Solution

  • The template parameter passed to the typeahead plugin can be either a compiled template or a string. If it's a string, the typeahead plugin will attempt to compile it. Don't do this with dust. Instead, compile the dust templates like normal, but pass the template parameter as something like:

    var compiled = dust.compile('Hello {name}!', 'myTemplate');
    dust.loadSource(compiled);
    
    $('selector').typeahead({
        template: fakeCompile('myTemplate')
    )};
    
    function fakeCompile (dustTemplateName) {
        return {
            render: function (data) {
                var html;
                dust.render(dustTemplateName, data, function (err,out) { html = out });
                return html;
            }
        }
    }
    

    Typeahead should use the "compiled" template as is without attempting another compile.

    EDIT Thanks to @user2103008, fixed dust render callback function signature.