nick gowdy
nick gowdy

Reputation: 6531

How to add to nested children of knockout observable array

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:

My global observable array

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

Answers (1)

nwayve
nwayve

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

Related Questions