mustachescalate

How can I plug a strategy to deal with missing attributes when using Mustache templates


I'm using mustache to render stuff on the server, but also on the client. The strategy is that I have a single page app (rendered with mustache on the server) and this template pulls snippets from the server and uses them to render json on the client too.

Now the problem is with the templates. I want to render the labels on the server, but leave some mustache syntax in place to be rendered on the client. Let's say I have a template like this:

<html>
<head><title>{{label.title}}</title></head>
<body>
    <h1>{{name}}</h1>
    <p>{{description}}</p>
</body>
</html>

Server side rendering will fill out the label, but now it also removes the placeholders that are not visible on the context.

<html>
<head><title>Ze zjerman title</title></head>
<body>
    <h1></h1>
    <p></p>
</body>
</html>

Is there a way to plug into Scalate and avoid this? I naively tried to get away with:

templateEngine.layout(path, Map(attributes:_*).withDefault((key)=>"{{"+key+"}}"))

... but obviously that will be discarded as soon as the map is processed through a loop (e.g. in TemplateEngine line 576). Where is the proper plug point for this?

I've also found the noneString and nullString in RenderContext, but I think I can't make the renderer output a key there, since these variables are just Strings...

I'm using scalatra-scalate 2.0.2 and scala 2.9.0-1.


Solution

  • You could use an alternate delimiter for the data you know will be populated client side. See: Set Delimeter

    Server side template:

    <h1>{{title}}</h1>
    <p> [[ client.name ]] - [[ client.description ]] </p>
    

    Server side data:

    {title : "Hello"}
    

    Prepend your alternate delimiter to the rendered server template and then render client side.

    var client_template = "{{=[[ ]]=}}" + server_rendered,
    client_data = { client : { name : "Max", description : "world"}},
    client_rendered = Mustache.render(client_template, client_data);
    

    I made a working jsFiddle to show it working. Check out the console.log to see the server template before and after.