Sevil Yilmaz
Sevil Yilmaz

Reputation: 123

Simultaneous external template loading and data binding with Knockout and Require

I want to send both requests for view and data, then when view and data requests responded they need to be binded. I use setInterval for this. But I don't know this is the correct way or not.

Sometimes I need to update most of ViewModel data. I can't figure out how can I update these mass data.

With this code I get both view and data. But I can't use data in viewModel. Because if I try to update data after binding I don't know what to do.

Any suggestions?

in app.js

crossroads.addRoute('/cart', function () {
    require(['cart'], function () {
        cart.init();
    });
});

in cart.js

define(['jquery', 'knockout'], function($, ko) {
    var cart = {
        viewLoaded: false,
        dataLoaded: false,
        template: '',
        cartData: {},

        container: '#container',

        // Gets external template
        getView: function () {
            $.ajax({
                ...
                success: function (response) {
                    cart.viewLoaded = true;
                    $(cart.container).html(response);
                }
            });
        },

        // Gets data
        getCart: function () {
            $.ajax({
                ...
                success: function (response) {
                    cart.dataLoaded = true;
                    cart.cartData = response;
                }
            });
        },

        ViewModel: function () {
            var self = this;

            self.cartId = ko.observable();
            self.products = ko.observableArray([]);
            .
            .
            .
        },

        // Checks both template and data are loaded
        bindings: function () {

            var loadControl = setInterval(function() {
                if (cart.viewLoaded && cart.dataLoaded) {
                    ko.applyBindings(new cart.ViewModel(), $(cart.container)[0]);
                    clearInterval(loadControl);
                }
            }, 100);
        },

        init: function () {
            this.getView();
            this.getCart();
            this.bindings();
        }
    };

    return cart;
});

Upvotes: 0

Views: 197

Answers (1)

Sevil Yilmaz
Sevil Yilmaz

Reputation: 123

I used callback function instead of interval. And when user change URL I remove DOM elements and bindings like this:

in app.js

var stepCart = crossroads.addRoute('/cart', function () {
    require(['cart'], function () {
        cart.init();
    });
});

stepCart.switched.add(function () {
    cart.stopEvents();
});

in cart.js

define(['jquery', 'knockout'], function($, ko) {
    var cart = {
            .
            .
            .

        // Gets external template
        getView: function (callback) {
            $.ajax({
                ...
                success: function (response) {
                    cart.viewLoaded = true;
                    $(cart.container).html(response);

                    if (typeof callback === 'function') {
                        callback();
                    }
                }
            });
        },

        // Gets data
        getCart: function (callback) {
            $.ajax({
                ...
                success: function (response) {
                    cart.dataLoaded = true;
                    cart.cartData = response;

                    if (typeof callback === 'function') {
                        callback();
                    }
                }
            });
        },

            .
            .
            .

        // Removes DOM elements and bindings
        stopEvents: function () {
            ko.cleanNode($(cart.container).get(0));
            $(cart.container).empty();
            this.viewLoaded = false;
            this.dataLoaded = false;
        },

        // Checks both template and data are loaded
        bindings: function () {

            if (cart.viewLoaded && cart.dataLoaded) {
                ko.applyBindings(new cart.ViewModel(cart.cartData), $(cart.container)[0]);
            }
        },

        init: function () {
            this.getCart(cart.bindings);
            this.getView(cart.bindings);
        }
    };

    return cart;
});

Upvotes: 0

Related Questions