PlTaylor
PlTaylor

Reputation: 7525

Durandal interfering with Knockout Bindings?

I have an application that I am building that is using Durandal and Knockout and there seems to be a problems when I use the durandal navigation to one of the pages in my SPA. When I load the application from the home screen and navigate to my second page that has a series of cascading dropdowns it appears as though the bindings break. If I refresh the page and load the second page to start with the bindings all seem to work as expected. The first page has nothing on it other than a title right now, and the second page has the cascading dropdowns. I am honestly not sure what code to include on this question so if there is anything people would like to see please feel free to ask. I am peeking into the Knockout context using the 'Knockout Context' Chrome plugin and everything seems to be working except the results are not displayed.

The simplier view model that is having problems

define(['services/logger',
    "services/datacontext"],
function (logger, datacontext) {
    var manufacturers = ko.observableArray();
    var manufacturer = ko.observable();
    var isSaving = ko.observable(false);
    var modelsWithSizes = ko.observableArray();

    manufacturer.subscribe(function (newValue) {
        datacontext.getBikeModelsWithSizes(modelsWithSizes, newValue.manufacturerID());
    });


    var hasChanges = ko.computed(function () {
        return datacontext.hasChanges();
    });

    var cancel = function () {
        datacontext.cancelChanges();
    };

    var canSave = ko.computed(function () {
        return hasChanges() && !isSaving();
    });

    var save = function () {
        isSaving(true);
        return datacontext.saveChanges().fin(complete);

        function complete() {
            isSaving(false);
        }
    };

    var canDeactivate = function () {
        if (hasChanges()) {
            var title = 'Do you want to leave ?';
            var msg = 'Navigate away and cancel your changes?';
            var checkAnswer = function (selectedOption) {
                if (selectedOption === 'Yes') {
                    cancel();
                }
                return selectedOption;
            };
            return app.showMessage(title, msg, ['Yes', 'No'])
                .then(checkAnswer);

        }
        return true;
    };

    var vm = {
        activate: activate,
        cancel: cancel,
        canDeactivate: canDeactivate,
        canSave: canSave,
        hasChanges: hasChanges,
        manu: manufacturer,
        manufacturers: manufacturers,
        modelsWithSizes: modelsWithSizes,
        save: save
    };

    return vm;

    //#region Internal Methods
    function activate() {
        manufacturers(datacontext.lookups.manufacturers),
        logger.log('Frames View Activated', null, 'frames', false);
        return true;
    }


    //#endregion
});

The datacontext call is as follows

datacontext.lookups = {
    manufacturers: function ()
    { return getLocal('Manufacturers', 'name', true); }
};

Upvotes: 1

Views: 940

Answers (2)

Jacques Snyman
Jacques Snyman

Reputation: 4300

If datacontext.lookups.manufacturers is a preloaded observableArray, you probably need to change your activate function to:

function activate() {
    vm.manufacturers(datacontext.lookups.manufacturers());
    logger.log('Frames View Activated', null, 'frames', false);
    return true;
};

If datacontext.lookups.manufacturers is a async call to the web api, you will want to change it to:

function activate() {
    logger.log('Frames View Activated', null, 'frames', false);
    return datacontext.lookups.manufacturers().then(querySuccess);

    function querySuccess(data)
    {
        vm.manufacturers(data.results);
    };
};

Upvotes: 0

RainerAtSpirit
RainerAtSpirit

Reputation: 3723

I'm not using breeze so I don't know if getLocal() is async or not, but if in doubt return a wrapped $.when(syncOrAsync).then(...).

function activate() {
    var manufacturesPromise = datacontext.lookups.manufacturers();
    logger.log('Frames View Activated', null, 'frames', false);

    return $.when(manufacturesPromise).then(function(results){
       manufacturers(results);
    });
}

Upvotes: 0

Related Questions