0

I am reading an existing code. Initially, the code initializes the property 'Data':

self.Data = ko.observable({});

but afterwards, in some function the code assigns 'Data' to something like below. self.Data is not set to an observableArray but below, it is used as it is though an array. No other code touches self.Data before this line so when it hits this line but before assignment, it is still a ko.observable({}).

self.Data()[0] = ko.observable("");

I was thinking that this is a legal syntax for converting an observable object to an array in knockout.js, but if I try to immediately put an alert for it length like alert(self.Data().length), it is undefined.

My question would be what does this code actually do?

g_b
  • 11,728
  • 9
  • 43
  • 80
  • I am not sure if self.Data = ko.observable({}); is a valid syntax for an observable. I would mostly do initialise an observableArray in this way – G_S Sep 23 '14 at 02:17

1 Answers1

1

It isn't an observable array. It's an object. With a javascipt object you can access it's properties by dot notation or index notation. link

Since javascript is dynamically typed you can add new properties to existing objects.

The following code is really just adding a new observable property to the existing object instance.

self.Data()[0] = ko.observable("");

Here is an example that will hopefully help you visualize what's going on.

var vm = function(){
  var self = this;
  self.data = ko.observable({});
  self.dataString = ko.computed(function(){return JSON.stringify(self.data(), null, 2);});

  self.propertyName = ko.observable(0);
  self.propertyValue = ko.observable('someValue');

  self.update = function(){
    //This adds a new property or updates an existing property of the object the self.data observable references.
    //The name of the property will be the value of the self.propertyName observable which will be the value typed into the first textbox in the UI.
    //The value of the property will be the value of the self.propertyValue observable which will bhe the value typed into the second textbox in the UI.
    self.data()[self.propertyName()] = self.propertyValue();
    //Need to force an update since the data observable wasn't directly modified
    self.data.valueHasMutated(); 
  };
  
  self.replace = function(){
    //Replace the existing value with a new object
    var data = {};
    data[self.propertyName()] = self.propertyValue();
    self.data(data);
  };
}

$().ready( function(){
  ko.applyBindings(new vm());
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

Property Name <input data-bind="textInput:propertyName" /> <br />
Property Value <input data-bind="textInput:propertyValue" /> <br />

<button data-bind="click:update">Update</button>
<button data-bind="click:replace">Replace</button><br />
The self.data observable represented as a json string:
<pre data-bind="text:dataString"></pre>
Community
  • 1
  • 1
Aaron Carlson
  • 5,522
  • 4
  • 31
  • 35
  • Hi Aaron, sorry but I'm a bit confused. Based on the link that you gave me, you can dynamically add a property in JavaScript by using index notation. But in my example (and yours), I can't seem to figure out what the new property name of data would be. Thanks. – g_b Sep 23 '14 at 03:40
  • Wait, I think you are saying that in your example self.data()[self.propertyName()], the property name is an observable object? Or is it just the new property is an observable object; no property name? How about in my example? – g_b Sep 23 '14 at 03:41
  • It's not a new property name of data but a property named 0 that is added to the object that the data observable references. – Aaron Carlson Sep 23 '14 at 03:42
  • self.data()[self.propertyName()] does not mean the property name is an observable. self.propertyName() unboxes the observable and returns the underlying value. In this case it will be whatever is typed into the first textbox in the ui. – Aaron Carlson Sep 23 '14 at 03:46