Reputation:
I am having trouble figuring out how to add to a pre-existing observableArray
after issuing a second AJAX request for similar, but different data.
My first JSON request does not contain the type called value
, so I need to add it. My initial JSON structure:
[{"statusmsg":"OK","data":{"status":"stopped"},"sender":"hostname","statuscode":0}]
A second AJAX request is issued which gets the uptime of a service from the REST server:
[{"statusmsg":"OK","data":{"value":"","fact":"some_fact"},"sender":"hostname","statuscode":0}
I want to add to the nested object data
the type value
, which contains some_fact
.
I have tried the following:
ko.utils.arrayForEach(self.rows(), function(row) {
ko.utils.arrayForEach(self.timeRows, function(time) {
if(row.sender() == time.sender()) {
self.rows()[0].data.push({value: time.data.value()});
}
});
});
Note: I am using the placeholder index 0 for testing only. Ideally, I would like to just find the match based on the hostname and update the observableArray
.
When this code executes, I receive the error that
TypeError: self.rows(...)[0].data.push is not a function
I also tried putting parentheses next to data
like data().push
, but that did not work either.
The intent is to add a new value to the original observableArray
called rows
so I can update my view with the new information.
Upvotes: 1
Views: 632
Reputation:
To solve my problem, I used @Sybeus' answer but then I realized that my rows were not updating in my UI because my UI was bound to the old version of rows. Even when I tried to create a dummy subscriber and notify my computed observable that the rows were updated, it was still bound to the old rows as described in this answer:
If you would want to replace the array you should probably create a replacement array, push tweets into that array and finally replace the array in the observableArray by doing self.tweets(replacementArray);.
So what I had to do was the following:
self.updateServiceStartTime = function() {
var url = "url";
$.ajax({
method: "GET",
url: url,
success: function(data) {
var observableData = ko.mapping.fromJSON(data);
var array = observableData();
self.timeRows(array);
ko.utils.arrayForEach(self.rows(), function(row) {
ko.utils.arrayForEach(self.timeRows(), function(time) {
if(row.sender() == time.sender()) {
if (time.data.value()) {
row.data.value = time.data.value;
}
else {
row.data.value = "No time found yet.";
}
}
});
});
self.cloneRows(self.rows().slice());
self.rows.removeAll();
self.rows(self.cloneRows().slice());
}
});
};
This updates the UI with the new data that I added.
Upvotes: 0
Reputation: 1189
Since you've opted for the default Knockout mapping, it automatically assumes an associative array is a simple object with attributes, and thus has no array prototype functions, such as push(). You don't need the index reference either, since you've already found the row
in self.rows()
. So just simply set the value
attribute of the 'data' sub-object of the matching row
object:
ko.utils.arrayForEach(self.rows(), function(row) {
ko.utils.arrayForEach(self.timeRows, function(time) {
if(row.sender() == time.sender()) {
row.data.value = time.data.value;
}
});
});
Upvotes: 3