Data binding multi select with data transformed

In ViewModel, options object is set from server and is in a format that is not friendly to data bind on UI
And the server expects the updated options (by user selections on UI) to be also in the same format.

optionsUI object of the ViewModel is a transformation that is easier to bind on UI. optionsUI.get transforms server format to UI format and it works fine. The optionsUI.set should update options to be saved on server which does not work.

Problem 1: The optionsUI.set function is not triggered when user changes selections on UI

Problem 2: And if thats fixed, I am not sure if that will lead to infinite updates between options and optionsUI. Then what is a good way to achieve this?

I was unable to get JSBin to include DefineMap correctly though can.map.define.js script is loaded in HTML.

I only had a second to look over the jsbin, but:

options: {
    value: [
      {
        key: "select1",
        value: ["one"]
      }, 
      {
        key: "select2",
        value: ["two", "three"]
      }
    ],
    "set": function ( newVal ) {
      this.optionsUI = newVal;
      return newVal;
    }
  },

should be

options: {
    value: function(){
      return [
        {
          key: "select1",
          value: ["one"]
        }, 
        {
          key: "select2",
          value: ["two", "three"]
        }
      ];
    },
    "set": function ( newVal ) {
      this.optionsUI = newVal;
      return newVal;
    }
  },

This makes sure the same object isn’t shared by every single instance.

Created an issue to warn people about the value thing: https://github.com/canjs/canjs/issues/3012

And an issue about better warnings when bindings can’t find data: https://github.com/canjs/can-stache-bindings/issues/136

1 Like

The issue here is that the select is cross bound to optionsUI.select1.

That value doesn’t exist. In CanJS 3.0, components don’t leak scope. Meaning there’s no options available because it’s not passed.

Setting leakScope:true fixes that problem but creates a stack overflow. Not sure why…

The other thing is you could pass optionsUI to homepage. Passing it looks a little weird because attribute names are case insensitive <home-page {options-u-i}="optionsUI"/>

1 Like

Thanks @justinbmeyer. Fixed the JSBin by making value as a function and passing correct arguments. However, whenever I change my selections on UI, the setter is not triggered. http://jsbin.com/secexek/edit?html,js,output

This was my initial dilemma that I am unable to get data binding working. So my three problems are:

  • Setter in JS pane on line 48 is not called when user changes selections

  • In JS pane, if I code as per line 49, results in STACK OVERFLOW. I understand why its happening, but want to avoid it and solve for the use case I initially explained in my question.

  • In HTML pane, line 22 does not show problem values

Feel free to update the Bin if thats allowed :smiley: