Search code examples
asp.net-mvcknockout.jsasp.net-mvc-5durandaldurandal-2.0

How can I convert this knockout view model to be Durandal compliant?


I have a system built on KnockoutJS and I am now trying to take advantage of Durandal. I have figured out how to make MVC routes play nicely with it and so am now quite comfortable in that respect. However, I am a little bit confused about the view models. I suppose the confusion lies with my ignorance of RequireJS. What I am looking for is a simple example for the following sample view model:

The following is a skeleton/example of what is very common in my system and so I would need to know how to make this play nicely with Durandal:

var SomeModelA = function () {
    var self = this;

    self.id = ko.observable(0);
    self.name = ko.observable(null);
    //etc

    self.create = function () {
        //etc
    };

    self.edit = function (id) {
        //etc
    };

    self.delete = function (id) {
        //etc
    };

    self.save = function () {
        //etc
    };

    self.cancel = function () {
        //etc
    };
};

var SomeModelB = function () {
    var self = this;

    self.id = ko.observable(0);
    self.name = ko.observable(null);
    //etc

    self.create = function () {
        //etc
    };

    self.edit = function (id) {
        //etc
    };

    self.delete = function (id) {
        //etc
    };

    self.save = function () {
        //etc
    };

    self.cancel = function () {
        //etc
    };
};

var ViewModel = function () {
    var self = this;

    self.someModelA = new SomeModelA();
    self.someModelB = new SomeModelB();
};

var viewModel;
$(document).ready(function () {
    viewModel = new ViewModel();
    ko.applyBindings(viewModel);

    $("#GridA").kendoGrid({
        //etc
    });
    $("#GridB").kendoGrid({
        //etc
    });
});

All I need is a really basic example based on the above.

And before anyone mentions it; yes I am aware of Aurelia - it's awesome and I will be using it in new projects... But my current system is making heavy use of Knockout and therefore it makes sense to go with Durandal for now... which may turn out to be a stepping stone towards Aurelia later anyway.

EDIT

Please note I have tried the following with no success:

JS:

var SomeModelA = function () {
    var self = this;
    self.name = ko.observable(null);
};
var SomeModelB = function () {
    var self = this;
    self.name = ko.observable(null);
};

define(['knockout'], function (ko) {
    return function () {
        var self = this;
        self.modelA = new SomeModelA(),
        self.modelB = new SomeModelB(),

        self.showA = function () {
            alert(this.modelA.name());
        },
        self.showB = function () {
            alert(this.modelB.name());
        }
    };
});

Markup:

<section>
    @Html.TextBox("NameA", null, new { @class = "form-control", data_bind = "modelA.name" })
    @Html.TextBox("NameB", null, new { @class = "form-control", data_bind = "modelB.name" })

    <button type="button" data-bind="click: showA" class="btn btn-default">Show A</button>
    <button type="button" data-bind="click: showB" class="btn btn-default">Show B</button>
</section>

The above does not seem to bind the data correctly. When i change something in the textbox, then click the button, I can see the values are still showing as "NULL". What am I missing here?


Solution

  • I was actually being pretty stupid here; forgetting to tell knockout what to bind to.. in this case, "value". So, the working example is as follows:

    JS:

    define(['knockout'], function (ko) {
        var SomeModelA = function () {
            var self = this;
            self.name = ko.observable('testA');
        };
        var SomeModelB = function () {
            var self = this;
            self.name = ko.observable('testB');
        };
    
        var vm = {
            modelA: new SomeModelA(),
            modelB: new SomeModelB(),
    
            showA: function () {
                alert(this.modelA.name());
            },
            showB: function () {
                alert(this.modelB.name());
            }
        };
        return vm;
    });
    

    Markup:

    <section>
        @Html.TextBox("NameA", null, new { @class = "form-control", data_bind = "value: modelA.name" })
        @Html.TextBox("NameB", null, new { @class = "form-control", data_bind = "value: modelB.name" })
    
        <button type="button" data-bind="click: showA" class="btn btn-default">Show A</button>
        <button type="button" data-bind="click: showB" class="btn btn-default">Show B</button>
    </section>