How to handle unknown properties at design time in knockoutJS

497 Views Asked by At

I am not sure, if I ask the question properly, so I try to explain the scenario. I have the feeling that I miss something simple in handling knockout.

I read (and later write to) multiple xml files. These files have some entries that are equal and some entries that differs:

<elements>
  <id>123</id>
  <unknown>some text</unknown>
</elements>

After reading the xml files I come up with an observableArray which I can access as mentioned in most tutorials without any problem.

So in this example I have no problem to read and edit the "id", cause I know that it calls "id":

<span data-bind="text: $data.id"></span>

But there are entries in the xml that i dont know, but they are in the observableArray and I can "see" that, if I refer to $data:

<pre data-bind="text: ko.toJSON($data, null, 2)"></pre>

This shows me the unknown parts:

...
{
  "unknown": "some text"
}
...   

To edit this property I had to access them by name or is there another option? So my problem is to access this for example via:

<input data-bind="value: $data.???" />

If more information is required, please let me know.

Thanks for ideas and answers.

2

There are 2 best solutions below

0
On BEST ANSWER

The html-markup:

<div data-bind="foreach: $data.elemente">
  <pre data-bind="text: ko.toJSON($data)"></pre>
  <ul data-bind="foreach: $root.element">
    <div data-bind="if: $parent[$data]" >
      <label data-bind="text: $data"></label>
      <input data-bind="value: $parent[$data]" />
    </div>
  </ul>
</div>

The Javascript Code:

    // this is for "click: selected"
    this.selected = ko.observableArray();

    this.element = ko.computed(function () {
      if (self.selected().length === 0) {
        return [];
      }
      var bez = [];
      var obj = self.selected().elemente;
      console.log(obj);
      for (var n in obj) {
        for (var i in obj[n]) {
          bez.push(i);
        }
      }
      return bez;
    });

The JsonObject which I correspond to (chrome view):

0: Object
   elemente: Array[3]
   0: Object
      meinfeld: "feldBalue1"
      __proto__: Object
   1: Object
      feldxyz: "xyzValue"
      __proto__: Object
   2: Object
      feld123: "Top 123"
     __proto__: Object

and the result in the browser:

the result in the browser

edit: A nice way is using a custom binding-handler:

ko.bindingHandlers.readXml = {
  init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
    console.log(allBindings());
    var xmlElements = getValueAccessor(valueAccessor());
    ko.bindingHandlers.foreach.init(element, xmlElements, allBindings, viewModel,   bindingContext);
  return {
    controlsDescendantBindings: true
  };
},
update: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
  var xmlElements = getValueAccessor(valueAccessor());
  ko.bindingHandlers.foreach.update(element, xmlElements, allBindings, viewModel, bindingContext);
}
};
2
On

You can convert the unknown data structure to a known ViewModel structure

Like

for(var name in data) {
   this.values.push(new ValueViewModel(name, data[name]));
}

http://jsfiddle.net/AKzLM/