{{input type='text value=model.foo'}}
<button {{action 'changeText'}}>{{model.buttonText}}</button>
EmberJs uses a templating language, Handlebars. Its approach is fundamentally different to that of AngularJs', as it uses a string-based templating mechanism, as opposed to a DOM-based templating mechanism. This means that it parses the entire template beforehand, and generates a series of functions that contain the static inputs to the templates in-line, and accept parameters for the dynamic inputs to the templates.
That explanation would be awfully hard to follow without context - so here is the compiled function that EmberJs + Handlebars would generate for the template specified above.
function anonymous(Handlebars,depth0,helpers,partials,data) {
this.compilerInfo = [4,'>= 1.0.0'];
helpers = this.merge(helpers, Ember.Handlebars.helpers); data = data || {};
var buffer = '', stack1, hashContexts, hashTypes, options, helperMissing=helpers.helperMissing, escapeExpression=this.escapeExpression;
hashContexts = {'type': depth0};
hashTypes = {'type': "STRING"};
options = {hash:{
'type': ("text value=model.foo")
},contexts:[],types:[],hashContexts:hashContexts,hashTypes:hashTypes,data:data};
data.buffer.push(escapeExpression(((stack1 = helpers.input || depth0.input),stack1 ? stack1.call(depth0, options) : helperMissing.call(depth0, "input", options))));
data.buffer.push("\n<button ");
hashTypes = {};
hashContexts = {};
data.buffer.push(escapeExpression(helpers.action.call(depth0, "changeText", {hash:{},contexts:[depth0],types:["STRING"],hashContexts:hashContexts,hashTypes:hashTypes,data:data})));
data.buffer.push(">");
hashTypes = {};
hashContexts = {};
data.buffer.push(escapeExpression(helpers._triageMustache.call(depth0, "model.buttonText", {hash:{},contexts:[depth0],types:["ID"],hashContexts:hashContexts,hashTypes:hashTypes,data:data})));
data.buffer.push("</button>\n");
return buffer;
}
Do not worry if that looks like gibberish to you -
simply look at how it alternately does data.buffer.push("some string");
and data.buffer.push(/* some expression */);
.
Those are the static and dynamic inputs respectively.
Ultimately, this function builds a string,
and that string is added to the rendered DOM.
The difference between DOM-based templating mechanisms and string-based templating mechanisms may be thought of as an outside-in approach versus an inside-out approach.
The string-based templating mechanism has some pros and cons:
<script>
tags in this caseAll of these are pretty minor considerations,
except for additional DOM nodes being inserted.
Littering the DOM with numerous <script>
tags makes it quite cluttered and ugly,
and makes inspecting it a lot less "fun".
It makes one wonder, surely, there must be a better way to do this!
The other implication of this is that two-way binding to element attributes
is simply not possible, using this syntax.
EmberJs gets around this by defining a special alternative syntax, {{bind-attr}}
.
All this put together makes it feel more like something tacked together, rather than a well engineered, elegant, solution.
Separately, the syntax allowed for expression within Handlebars templates is quite restrictive. Properties may only be looked up and output as-is. If any processing or formatting is required, the only way to do this is by defining properties on a controller, or by registering Handlebars helper functions.