Rather odd binding behaviour in stache

It seems as though binding to an attribute can be unpredictable.

In example 1 there is a binding directly in the template to username even though it is not defined in the associated can.Map and everything still seems to work Ok.

In example 2 there is no direct binding but there is indirect binding through the components. This does not appear to work with the undefined username in the empty associated can.Map.

However, example 3 is identical to example 2 except that the associated can.Map({ username: '' }) now does not have an empty username.

This behaviour is certainly not ideal. Am I perhaps missing something?

The problem is that setting doesn’t exactly know where to set unless a value is established.

This is in many ways the equivalent of code like the following in JS:

var func1 = function(){
  var varA;
  return function func2(){
    var varB;
    varC = "SOMETHING";
  } 
}
func1()()

where does varC get set if a variable isn’t established? In JS it gets set as window.varC. In stache, it will set the most immediate scope.

Basically, stache is setting username on a local context. You can sorta see this here: http://justinbmeyer.jsbin.com/mozoje/edit?html,js,output

Ok. Makes sense.

This means that one needs to be rather careful when/how you create a viewModel using a function.

@eben_roux I’m not sure exactly where you are in terms of understanding the available binding syntaxes, but your usage of value="username" on the component element and {($value)}="{{value}}" in the component’s template suggests to me that you are not aware that you can use direct bindings throughout the entire example, which would allow you to avoid this odd behavior.

I would do something like this:

<!-- 2-way bind component `value` to parent `username` -->
<core-textbox {(value)}="username"></core-textbox>
<!-- 2-way bind input's value to component's `value` -->
<input {($value)}="value">

This method still allows a lot of composability because you can specify to which parent property the input element will be bound in each instance of the component. The direct bindings also simplify debugging because you don’t have to wait for stache to update {{value}} which takes a turn.

Thanks Dylan,

That is quite interesting. In Ember one would have value="username" for passing a value and valueBinding="username" for two-way binding. So I need to get used to how this all works in canjs. Your solution is, quite obviously, the way to do it correctly :slightly_smiling:

Regards,
Eben