2
votes

I'm working on a Durandal SPA, and I've setup some views and viewmodels. I'm unclear how I should be creating "model" objects on the client side. For instance, let's say that I want to define and create "Person" model object.

Everything else in my app is defined AMD style. This allows Durandal/RequireJS to automatically load up the files it needs.

So, my first thought was that I might define my "Person" model type in a models/person.js file, like this:

define(function () {
    var id = ko.observable(0);
    var firstname = ko.observable('');
    var lastname = ko.observable('');

    return = {
        id: id,
        firstname: firstname,
        lastname: lastname,
    };
});

However, I don't think this is right, because from here I don't think there's a way to actually create individual "Person" objects. For instance, let's say I wanted to create two "Person" objects. Durandal/RequireJS will happily load in my "Person" module, but it's just one object--and I may want to create another instance of the "Person" type, or five more instances, etc.

What's the appropriate way to do this? Thanks for helping clear up my confusion!

UPDATE: I've gotten some responses that explain some ways to do this. I think my confusion stemmed from the fact that a "module" is not a "type", or a "class". It's more like a singleton object. So if you want to define a type, and put it inside a module, you need to create module that is, essentially, a factory.

Is that right?

A factory makes sense in this case. But, I have a clarifying question: is this a factory the accepted method for defining model types in a Durandal/RequireJS/AMD style JavaScript app? I'm sure I'm not the first person to run into this issue. I'm wondering how it has been solved before, and (especially) if there is an accepted convention in the AMD world on how to define reusable types.

2

2 Answers

3
votes
define(function () {

    return function(){
       var self = this;
       self.id = ko.observable(0);
       self.firstname = ko.observable('');
       self.lastname = ko.observable('');
    };
});

define(['models/person'], function(person){
    var myPerson = new person();
});
1
votes

A "person" doesn't really sound like a concept that can be turned into a module, but how about a "PersonFactory"?

person-factory.js

define(['knockout'], function (ko) {
    return {
        spawnPerson: function () {
            var id = ko.observable(0);
            var firstname = ko.observable('');
            var lastname = ko.observable('');

            return {
                id: id,
                firstname: firstname,
                lastname: lastname,
            }
        }
    }
});

It could be used in another module in the following manner:

do-something-with-person.js

define(['person-factory'], function (PersonFactory) {
    var newPerson = PersonFactory.spawnPerson();

    return {
        // do something with newPerson
    }
});