2

I am building an application using Durandal and I have the need to share some functionality across view models.

I have 5 screens to build and they are all virtually the same screen except that in the activate function they will call to a different api end points but otherwise the view and view models will be identical.

Is there a pattern that I should be following to structure this correctly to promote code reuse?

PW Kad
  • 14,953
  • 7
  • 49
  • 82
Alexander Preston
  • 1,665
  • 11
  • 15
  • I would look at durandal's samples folder and take a look at the masterDetail sample. I think that might be similar to what your talking about. – Evan Larsen Mar 26 '13 at 12:52

1 Answers1

4

If the views and the view models are identical except for calling different api actions, what about just taking in a parameter as part of the route? Then in the activate function, you can switch on the parameter. The route values can be designated so that your url is relevant, like [http://site/page/subtype], where subtype is the parameter (instead of using numeric values)

Regarding inheritance, depending on the features you need, there's so many ways to do JavaScript inheritance it can be a little confusing. There are some full-featured inheritance models provided by libraries such as base2 and Prototype. John Resig also has an inheritance model that I've used successfully.

In general, I prefer to stick to simpler solutions when it comes to JS inheritance. If you need a pretty much the full set of inheritance features, those libraries are good to consider. If you only really care about accessing a set of properties and functions from a base class, you might be able to get by with just defining the view model as a function, and replacing the function's prototype with the desired base class. Refer to Mozilla's Developer Docs for good info on inheritance.

Here's a sample:

 //viewModelBase
define(function (require) {
    "use strict";

    function _ctor() {

        var baseProperty = "Hello from base";
        function baseFunction() {
            console.log("Hello from base function");
        }
        //exports
        this.baseProperty = baseProperty;
        this.baseFunction = baseFunction;
    };

    //return an instance of the view model (singleton)
    return new _ctor();
});

//view model that inherits from viewModelBase
define(function (require) {
    "use strict";

    function _ctor() {

        var property1 = "my property value";
        function activate() {
            //add start up logic here, and return true, false, or a promise()
            return true;
        }
        //exports
        this.activate = activate;
        this.property1 = property1;
    };

    //set the "base"
    var _base = require("viewModelBase");
    _ctor.prototype = _base;
    _ctor.prototype.constructor = _ctor;

    //return an instance of the view model (singleton)
    return new _ctor();
});

Keep in mind this example all results in what effectively is a singleton (i.e. you'll only get the same instance, no matter how many times you require() it)

If you want a transient (non-singleton) just return _ctor. Then you'll need to instantiate a new instance after you require() it.

One more note, in general, functions should be defined on the prototype, not within the constructor function itself. See this link for more information on why. Because this example results in only a single instance, it's a moot point, so the functions are inside the constructor for improved readability and also the ability to access the private vars and functions.

Community
  • 1
  • 1
Joseph Gabriel
  • 8,339
  • 3
  • 39
  • 53
  • Thanks for the suggestion, it's a good point. It would get around the scenario I outlined. I'm really interested to know how to achieve inheritance in view models though. – Alexander Preston Mar 26 '13 at 14:17
  • 1
    Edited to include some additional info specifically regarding inheritance. – Joseph Gabriel Mar 26 '13 at 15:56
  • Thanks very much @heiserman, really helpful, learnt a lot there. Do you mind posting what viewModelBase would look like? – Alexander Preston Mar 26 '13 at 22:25
  • 1
    no problem. The more code I added, the more I felt like I'd better test it, so I did. As a result, there are a couple of tweaks from the original version, but this code does work in a Durandal app. – Joseph Gabriel Mar 27 '13 at 12:15