Issue with Closure Template (soy templates) rendering via Javascript & jQuery

664 Views Asked by At

I'm using javascript along with jQuery to render the closure templates (soy templates). I'm follwing its hello world example.
My jsfiddle here .

As described in the example, the following code works,

document.write(soy.examples.simple.helloWorld());

& provides

Hello world!

But when used along with jQuery to dynamically insert the closure template's content, its always returns empty, nothing gets appended. $('#withoutContent').append(soy.examples.simple.helloWorld());


Ironically,on further looking, the following jQuery works correctly

$('#withContent').append(soy.examples.simple.helloWorld().content);


i'm facing this issue while upgrading from a very old version of closure templates. We have a lot of such templates, updating each one's usage in javascript to use .content is cumbersome & errorprone.
Why isn't jQuery able to properly get the contents of the template??

1

There are 1 best solutions below

0
On

Why isn't jQuery able to properly get the contents of the template?

A call to soy.examples.simple.helloWorld() returns this object:

{
  constructor: function(){goog$soy$data$SanitizedContent.call(this)},
  content: "Hello world!",
  contentDir: null,
  contentKind: { ... },
  getContent: function(){return this.content},
  toString: function(){return this.content}
}

As you can see, it's not HTML, it has a couple of properties and methods - one of them is toString(), which returns the .content.

document.write() expects a string argument. If you pass something else (for example the object above) then it will call .toString() for you automatically. This is why

document.write(soy.examples.simple.helloWorld());

works.

jQuery's $.append() accepts all kinds of things - plain strings, single DOM nodes, DOM node lists, other jQuery objects, functions - and does the appropriate thing for each argument type. But in exchange for this flexibility it won't simply convert its argument to string. Some random object jQuery does not recognize will be discarded. This is why

$('#withoutContent').append(soy.examples.simple.helloWorld());

does not work.

updating each one's usage in javascript to use .content is cumbersome & errorprone.

If you can type$('...').append() in all of those locations, then you can type .content in all of those locations.