This is a known "feature" with Closure templates: http://code.google.com/p/closure-templates/issues/detail?id=25
The Closure compiler does name replacement on the template parameters, so that after the compilation the argument names are no longer "greeting" and "year". The JS object constructed in ClojureScript does not use dot notation, so those keys are not subject to the same name replacements. The workaround described in the ticket involves using bracket notation inside the templates: {namespace example.templates} /** * @param data */ {template .welcome} <h1 id="greeting">{$data['greeting']}</h1> The year is {$data['year']}. {/template} The template now expects one top-level argument called data. You'll need to wrap the map you pass to the template. Also, the emitted JS must use dot notation: (defn ^:export say-hello2 [message] (let [hello (dom/getElement "hello") data {:greeting message :year (. (date/Date.) (getFullYear))} data-wrapped (js-obj)] (set! (.data data-wrapped) (map-to-obj data)) (soy/renderElement hello tmpls/welcome data-wrapped))) Unfortunately this approach can quickly become unwieldy when you start using nested templates. If you're only passing literal data to templates, you could also define a macro which emits the kind of code that uses dot notation. Then you wouldn't need to do anything special in your templates. On Jul 25, 2:09 am, Jack Moffitt <j...@metajack.im> wrote: > I'm working through Closure tutorials translating them to > ClojureScript. Unfortunately, I've hit a problem where the code works > with {:optimizations :simple} but fails with {:optimizations > :advanced}. > > The code is very simple. It basically is a trivial template example > with Soy (from Closure templates). Here's example/core.cljs: > > (ns example.core > (:require [goog.dom :as dom] > [goog.date :as date] > [soy :as soy] > [example.templates :as tmpls])) > > (defn map-to-obj [m] > (.strobj (reduce (fn [m [k v]] > (assoc m k v)) > {} > (map #(vector (name %1) %2) (keys m) (vals m))))) > > (defn ^:export say-hello [message] > (let [hello (dom/getElement "hello")] > (dom/setTextContent hello message))) > > (defn ^:export say-hello2 [message] > (let [hello (dom/getElement "hello") > data {:greeting message > :year (. (date/Date.) (getFullYear))}] > (soy/renderElement hello tmpls/welcome (map-to-obj data)))) > > And the template hello.soy: > > {namespace example.templates} > > /** > * @param greeting > * @param year > */ > {template .welcome} > <h1 id="greeting">{$greeting}</h1> > The year is {$year}. > {/template} > > The template is compiled to hello.soy.js. I pass in the path to > hello.soy.js as well as closure-templates/javascript during compile. > > The HTML: > > <!DOCTYPE html> > <html> > <head> > <title>Example: Hello World</title> > </head> > <body> > <div id="hello"></div> > > <script src="hello-cljs.js"></script> > > <script> > example.core.say_hello2("Hello World!"); > </script> > </body> > </html> > > With simple optimizations, this produces the expected output. With > advanced optimizations both fields of the template are undefined. > > I'm probably doing something silly. Any ideas? > > jack. -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en