Justin
Justin

Reputation: 3397

How should my objects be structured for proper MVVM in Knockout?

I'm working with knockout and am trying to stay true the MVVM structure and trying to make the objects have that dependency on each other.

Here is what I currently have, be gentle, I'm still learning this:

Model, ViewModel, Service definitions:

var App = window.App || {};

(function(ns, $, ko) {
    ns.Models = {};
    ns.ViewModels = {};
    ns.Services = ns.Services || {};

    //Service def
    ns.Services.SearchService = function() {
        this.SearchByName = function(name, callback) {
            $.get("/api/SearchByName/" + name, function(d){
                callback(d);
            });
        };
    };

    //Model Def
    ns.Models.SearchResultModel = function(json) {
        var self = this;

        ko.mapping.fromJS(json, {}, self);
    };

    //ViewModel def
    ns.ViewModels.SearchResultsViewModel = function() {
        var self = this;

        self.dataService = new ns.Services.SearchService();
        self.SearchResults = ko.observableArray();

        self.GetSearchResultsByName = function(name){
            self.dataService.SearchByName(name, function(d) {
                $.each(d, function(i, e) { self.SearchResults.push(new ns.Models.SearchResultModel(e)); });
            });
        };
    };
}(App, jQuery, ko));

And I can currently use it like so:

var vm = new App.ViewModels.SearchResultsViewModel();

vm.GetSearchResultsByName("Doe");

ko.applyBindings(vm, document.getElementById("search-results-form"));

This is just my starting point and it seems like the ko.applyBindings(...) should be in the ViewModel somewhere.

With all that, am I going the right direction for this or am I completely off with it?

Upvotes: 1

Views: 137

Answers (1)

Timothy Shields
Timothy Shields

Reputation: 79441

Nothing unusual looking. It's a hard question to answer because if there isn't something you're doing wrong, there's not much to say...

One thing I noticed was that

$.get("/api/SearchByName/" + name, function(d){
    callback(d);
});

should by replaced with

$.get("/api/SearchByName/" + escape(name)).done(callback);

The name should be escaped because it might contain invalid URL characters, and there's no reason to wrap the callback. (In general, the expression function (x) { f(x) } is just adding unnecessary indirection to the simpler expression f.)

In the GetSearchResultsByName function, a name more descriptive than d would be good, especially since you're being so verbose with your naming elsewhere.

Upvotes: 1

Related Questions