Reputation: 1362
I am updating my Knockout object in Knockout and am verifying via the console that it is getting updated correctly. But the dropdown is not getting refreshed with the new value. If I refresh the page manually, the dropdown will be updated. I think I need to make something observable, but not totally sure.
This is my KO viewmodel:
var SellerViewModel = function(groups) {
var self = this;
self.json = groups;
self.groups = ko.computed(function() {
var opts = [];
for(var key in self.json)
{
if(self.json.hasOwnProperty(key))
{
opts.push({Text: self.json[key].majorGroup + " / " + self.json[key].minorGroup, Value: self.json[key].groupId});
}
}
return opts;
});
self.addGroup = function(json) {
var group = JSON.parse(json);
self.json.push(
{
"ExtensionData":{},
"contractId":"10006",
"groupId":group.groupID,
"imageId":null,
"majorGroup":group.majorGroup,
"minorGroup":group.minorGroup
}
);
console.log(JSON.stringify(self.json));
};
And my HTML dropdown:
<select data-bind="value: roomID, options: $root.groups, optionsValue: 'Value', optionsText: 'Text', optionsCaption: ' -- select a room --', disable: disableRoom" class="form-control" id="@roomID"></select>
And finally, this is how the dropdown gets populated on pageload:
var groups = @Html.Raw( Json.Encode(ViewBag.GroupDetail.SellerGroup) );
sellerViewModel = new SellerViewModel(groups);
Forgot to add one last snippet. This is how I am adding an additional item into the knockout object, which is supposed to update the dropdown.
var json = '{"majorGroup" : "' + major + '", "minorGroup" : "' + minor + '", "groupID" : "' + groupID + '" }';
sellerViewModel.addGroup(json);
My guess is that self.groups needs to be an observable array. But I don't know how to do that because I set it equal to ko.computed already.
Upvotes: 0
Views: 279
Reputation: 35222
As @pimbrouwers already mentioned, you need to make json
an observableArray
if you want the UI updated whenever the array changes.
self.json = ko.observableArray(groups);
You can make some improvements to your code. Instead of looping through indexes of self.json
and checking hasOwnProperty
, you could use map
:
self.groups = ko.computed(function() {
// if "json" is not an observableArray, then "self.json.map"
return self.json().map(function(group) {
return {
Text: group.majorGroup + " / " + group.minorGroup,
Value: group.groupId
}
})
});
And you are concatenating and forming a json in string format and then parsing it back. Instead, you could send an object itself.
var group = {
majorGroup: major,
minorGroup: minor,
groupID: groupID
}
sellerViewModel.addGroup(group);
And remove the JSON.parse()
from the self.addGroup
.
Here's a fiddle for testing with all these changes
You can also go through this answer to know more about the difference between json and javascript object literal
Upvotes: 1
Reputation: 12577
This is a simple problem, with a simpler solution.
self.json = ko.observableArray(groups);
In order for your computed
to fire, it needs to register a "subscription". Right now, you have it tied to just a normal JavaScript variable (by the look of the push()
I'm guessing it's an array).
Making self.json
an observable array will create this subscription for you.
Upvotes: 1