6

My app view model is growing very large. How do I properly split it up into files and namespaces? Do I create a second namespace object and have the view model be passed in as a parameter?

var BALL = {};
BALL.roll = function(avm) { // function code };
MKaras
  • 2,063
  • 2
  • 20
  • 35
  • 3
    This answer might help you: http://stackoverflow.com/questions/8676988/example-of-knockoutjs-pattern-for-multi-view-applications. It has three options for using multiple view models in Knockout. – RP Niemeyer Feb 09 '12 at 14:07

1 Answers1

11

My personal preference is not to split up my applyBindings calls and instead work with a single global namespace branch off of this.

My reasoning is that for multiple bindings to work correctly and not conflict you need to be very careful your selected target dom elements do not change. Unfortunately the markup has a nasty habit of changing over time which can get you in trouble with your viewModels later on.

My general approach which i've used on a very large KO project has been

  1. One global top level namespace for the whole app eg myapp
  2. Split up separate functional blocks into separate files. Usually with their own distinct namespace. e.g. `myapp.navigation'
  3. If one namespace in particular gets too big split it into further sub namespaces or if that is not appropriate split the same namespace across multiple files.
  4. Mash all the files at the end to preserve performance.

Some namespace code I've recently been using

var Namespace = (function() {
    var namespace, global, root;

    namespace = function(identifier, contents) {
        if (!identifier || identifier.length == 0) {
            throw Error("A namespace identifier must be supplied");
        }
        global = window;

        // create the namespace
        var parts = identifier.split(".");
        for (var i = 0; i < parts.length; i += 1) {
            if (!global[parts[i]]) {
                global[parts[i]] = {};
            }
            if (i == 0) {
                root = global[parts[i]];
            }
            global = global[parts[i]];
        }

        // assign contents and bind
        if (contents) {
            global.$root = root;
            contents.call(global);
        }
    };

    return namespace;
})();

So in your myapp.navigation file you would have

Namespace("myapp.navigation", function() {
     var self = this; // your myapp.navigation object

     this.someFunction = function() {
     }       
});

This is just shorthand for using a self invoking function to pass in a manually constructed namespace. It gives you a private closure and you are free to use multiple Namespace calls with the same namespace in different js file.

Your applyBindings call can now always be

ko.applyBindings(myapp);

Hope this helps.

madcapnmckay
  • 15,782
  • 6
  • 61
  • 78