-1

I'm having some trouble accessing data from a serialised Dictionary<string, CustomType> using javascript. The following json is the output of the my serialised dictionary.

The JSON generated is:

items: 
{
    "Books":{
        "Type":2,
        "Count":20547
    },
    "Games":{
        "Type":1,
        "Count":2647
    },
    "Films":{
        "Type":0,
        "Count":57213
    }
};

Inside my javascript file i've created an observable:

ko.observable(items)

The issue i'm having is accessing this information in my view. I need to dynamically retrieve the data based on a 'key' value. I've tried using:

@{ var key = Model.Key; }
<p data-bind="text: items[@key].Count"></p>

However, I get the following error:

Uncaught ReferenceError: Unable to process binding "text: function (){return items[Film].Count }"
Message: Film is not defined

Using c#, I can access the value for a particular key by using items["Books"]. Is it possible to achieve this using knockout?

tbonejenkins
  • 359
  • 3
  • 16
  • `options.items.Books`? – haim770 Jan 10 '16 at 15:23
  • The code you've posted makes no sense. It's at best incomplete, and if I imagine how the complete picture would probably be I'd say you have a KO error about creating an `observableArray` providing it a non-array. Please include a full repro of your situation in your code (see "[mcve]" for guidance). – Jeroen Jan 10 '16 at 15:42

1 Answers1

1

JavaScript objects behave like dictionaries (more exactly associative arrays) regarding how you can access their properties. For example doing this:

var items = {};
items.Books = { "Type":2, "Count":20547 };
items.Games = { "Type":1, "Count":2647 };

is completely equivalent to this:

var items = {};
items["Books"] = { "Type":2, "Count":20547 };
items["Games"] = { "Type":1, "Count":2647 };

Of course, you can also use this syntax to read the values:

var books = items["Books"];

As long as using it in ko, you cannot use observableArray, because it requires a JavaScript array, whose members are accessed by index. I.e. the items object in the previous example is an object with properties, and not a JavaScript array.

So, in ko you need to use an observables, like this:

var obs = ko.observable(items);

But this observable will only notify changes when the whole items object is changed, not when any of its properties, like Books, is modified. If you need to get notifications (for example to udpta the view) when some of these properties changes, then you need to make observable the properties themselves, not onbly the root object items. To do so, you can use ko.mapping plugin, or manually do it. This would be equivalent to do:

var items = ko.observale({
    Books: ko.observable({
      Type: ko.observable(2), 
      Count: ko.observable(20547)
    }),
    Games:  ko.observable({
      Type: ko.observable(1), 
      Count: ko.observable(2647)
    })
});

In this case, whenever any of the properties changes, this will be notified.

However, if yu needed to notify when you added or remvoed a property like Books, or Games, there would be not direct way to work like that in ko. You'd need to map your object to a regular observable array, and make a ko.observableArray to ge it working. The mapping could be like this:

var items = [
  { Name: 'Books', Type: 2, Count: 20547 },
  { Name: 'Games', Type: 1, Count: 2647 }
];

If you do so, you can create an observable array. If you still need to access the properties by Name, you can use JavaScript methods (depending on the version of EcmaScript supported by your browser) or use a library like lodash or underscore, which offers powerful ways to access, and map JavaScript objects and collections.

NOTE: ko expressions are able to detect that something is an observable, and unwrap its value. However, if you need to access an observabe property of an observable object, you have to use parentheses in the all levels, but the final, for example data-bind="value: items().Books().Type", in the case you used ko mapping or mapped it as explained in the code block before the last one. If you need more info, please, read this: When to use or not use parentheses with observables in data-binding expressions.

Community
  • 1
  • 1
JotaBe
  • 34,736
  • 7
  • 85
  • 109