Reputation: 6531
I have some code where to add to a knockout observable array I am converting the observable array into an object, unshifting a new object and then mapping this object back to view model. This works but it seems very slow. It takes around 2-5 seconds or more.
function addContact(office) { // Passing in object array of agency. We no it contains correct office and agency ID
// Assign observable data to new variable then remove old
// variable from mapping
var objAgency = ko.toJS(agency);
vm.agency.removeAll();
// Fill new object with empty strings and related data
var objContact = {
agencyID: office.agencyID._latestValue,
emailAddress: "",
firstName: "",
jobName: "",
office: "",
OfficeID: office.officeID._latestValue,
personID: "",
surName: "",
title: ""
}
// unshift where office ID match
for (i in objAgency[0].offices) {
if (!isNaN(i)) {
if (objAgency[0].offices[i].officeID === objContact.OfficeID) {
objAgency[0].offices[i].contacts.unshift(objContact); // At i remove one object
}
else {
}
}
}
vm.agency([ko.mapping.fromJS(objAgency[0])]);
}
I have tried adding to my observable instead of doing the conversion process and I got this error:
Unhandled exception at line 9423, column 13 in http://localhost:13762/scripts/breeze.debug.js
0x800a01b6 - JavaScript runtime error: Object doesn't support property or method 'getProperty'
This is the code that causes the error
for (i in agency._latestValue[0].offices._latestValue) {
if (!isNaN(i)) {
if (agency._latestValue[0].offices._latestValue[i].officeID = objContact.OfficeID) {
agency._latestValue[0].offices._latestValue[i].contacts._latestValue.unshift([ko.mapping.fromJS(objContact)]);
}
}
}
See my screenshot for what agency looks like:
What is the correct way to add to this observable array? As I understand latest value is a mechanism for tracking change so I shouldn't tamper with that?
Upvotes: 0
Views: 688
Reputation: 2331
If I'm not mistaken, ._latestValue
is a property when you're referencing the knockout-{version}.debug.js file. If you use knockout-{version}.js, that won't be there. In any case, myObservable._latestValue === myObservable() === ko.unwrap(myObservable)
. You don't want to reference _latestValue
because when you use the minified knockout js file in production, this code will break. You should rewrite your code to:
for (i in agency().offices()) {
if (!isNaN(i)) {
if (agency().offices()[i].officeID = objContact.OfficeID) {
agency().offices()[i].contacts().unshift([ko.mapping.fromJS(objContact)]);
}
}
}
And it's still not right because your if
comparison isn't a comparison, it's an assignment. Use ===
: if (agency().offices()[i].officeID === objContact.OfficeID)
That might do it, but I doubt it because I suspect agency().offices()[i].officID
is also an observable, in which case you'll need to use the ()
to access its underlying value.
Another problem is that you're unshifting an array into an array, kind of like this:
var arr = ["A", "B"];
arr.unshift(["Z"]);
// Result: [["Z"], "A", "B"];
So lose the brackets inside the .unshift function, unless you're intending to add an array to your array. Some people like to yo dawg.
And although you can call offices().unshift(value);
and manipulate the underlying array, it's preferable that you call unshift on the observableArray directly like this: offices.unshift(value);
because KO will then notify subscribers and update the DOM. Otherwise, you have to inform KO that the value has mutated. See the difference in this fiddle.
Hopefully that will help resolve your issue.
Upvotes: 1