Canjs binding with nested object


#1

HI everybody,
what is the proper way to bind nested object, in a parent-child scope, when importing a component?

I tried the following way, but it creates a new property called “object1.user” in the module1 viewModel that will coexist with the object1.user (the object is not merged).

It seems only working with simple properties, but I guess there is something wrong in my understanding.

// module/module1
var vmMap = Map.extend({ 
       "object1":{ 
          value: { "user":"an_user",
                       "data":"some_data"
                     }
       }
});

Component.extend({
           tag: "my-tag",
           viewModel: vmMap,
           view: can.view("<p>hi {{object1.user}} </p>");
}


// main page renderer with a viewModel that has a key "mainpage.username" and that will import 
// the module/module1 trying to pass bind the "mainpage.username" to "object1.user"

<can-import from="module/module1" >
    {{#if isResolved}}
       <my-tag {(object1.user)}="mainpage.username" ></my-tag>
    {{/if}}
    </can-import>

Thank a lot for the support!


#2

if object1 is an object (let’s assume of type User) you can bind mainpage.username to a property on object1 and the right binding syntaxe for parent->child:

<can-import from="module/module1" >
    {{#if isResolved}}
       <my-tag {object1.user.username}="mainpage.username" ></my-tag>
    {{/if}}
    </can-import>

I see you are using CanJS 2.x so here is the details on the docs
http://v2.canjs.com/docs/can.view.bindings.toChild.html


#3

Thank you @cherif_b,

I tried but i have the same problem.
I’m using the same syntax to access to the object proprieties, but with the two-way binding.

Maybe when i declare the “Key” object inside the component’s viewModel, should I use a Map or an extension of that? With an JavaScript Object declaration ( in the example is setter ad default value, with object literal) Will not work?

I’m working with canjs v3.

Thank again.


#4

Here is the example:
JSBIN EXAMPLE
when I tried to pass the object from the parent to the child (component) and bind the childobj.valueKey1, it creates a new “props” inside the viewModel.


#5

Any suggestion about this issue?
No One can help me?
Thanks.


#6

Sorry to ask this, but can you write up a really quick example? I don’t have time to digest the JSBin right now (multiple templates / components /etc).

You might be able to use setters or type converters or http://canjs.com/doc/can-connect/helpers/map-deep-merge.html


Can binding with nested object: dom element attributes
#7

Ok @justinbmeyer, I try to summarize the JSBIN (I made there a brief example with only the configuration to explain my problem):

When I include, a stache template, a new component (let’s say child-content) and configure a binding between the prop in the parent scope (let say key1) and a component’s viewModel prop (valuekey1) that is itselfs a prop on an object (or a Map - childObj), so I reference it with childobj.valuekey1 , the binding process will create a new prop (and a new value) in the viewModel called “childobj.valuekey1” instead of (i supposed) “merging” the childobj and pointing to the childobj[“valuekey1”] value (used the array notation only for clarify the referencing);

So, doing this:

<child-content {childobj.valuekey1}="key1" ></child-content>

Declaring the child-content viewModel as (for example):

var childMap = can.DefineMap.extend({
   valuekey1: {
     value: "default childObject valueKey1"
   },
  valuekey2:{
    value: "default childObject valueKey2"
  }
});

var childViewModel = can.DefineMap.extend({
  "childobj":{
    // 1.
    Value: childMap
  }
});

I get this when I check the child-content’s viewModel.

childobj: [object Object] {
    valuekey1: "default childObject valueKey1",
    valuekey2: "default childObject valueKey2"
  },
  childobj.valuekey1: "parent key 1"
}

Maybe my mistake is in the binding syntax {childobj.valuekey1} (dot notation to reference the property it? missing something?)

Thank for the help!