0
votes

I created a new VS2012 project using the hottowel template, which in return uses durandal, knockout and breeze.

I want to use jaydata instead of breeze and for the ui layer I want to use the excellent asKendoDataSource() functionality to power a kendoui grid.

I followed all the instructions to make kendoui work well with durandal. This is fine.

I have a model in which I get the jaydata entities and run asKendoDataSource() on it. My view is an MVVM declared kendoui grid with its source property set to the viewmodel's property that contains a reference to the asKendoDataSource().

In the knockout world the viewModel property would be an empty entities = ko.observableArray() which would then would be initialized by using entities(values) when the data service returns.

I need to mimic this such that I have a viewModel property that is an empty kendo datasource which then is initialized by the asKendoDataSource() conversion when the data comes back from jaydata. This way the mvvm kendo grid is bound initially to the empty datasource and then receives its items when the asKendoDataSource() is called.

This is all because the model - viewModel binding in durandal is asynchronous and there needs to be a placeholder property in the viewModel from the very beginning, which then, after the viewModel's activate() method promise is resolved, gets updated with the bound data and in return powers the DOM that the viewModel is bound to.

I can't figure out how to mimic the knockoutjs practice of an empty observable array which is bound to the dom and then (the same exact reference) gets initialized and populates the dom. There seems to be no way to create an empty kendo datasource which then is re-initialized by the asKendoDataSource() method. Reassigning the viewModel property to the new data source doesn't work because the kendo grid is bound to the original reference.

This is my airport view:

<section>
    <h2 class="page-title" data-bind="text: title"></h2>
    <div id="airportGrid" data-kendo-role="grid" data-kendo-sortable="true" data-kendo-pageable="true" data-kendo-page-size="25" data-kendo-editable="true" data-kendo-columns='["Id", "Abbrev", "Name"]' data-kendo-bind="source: airports"></div>    
</section>

This is my datacontext:

define([
    'durandal/system',
    'services/logger'],
    function (system, logger) {


        var getAirports = function (airportsObservable) {
            $data.Entity.extend("Airport", {
                Id: { type: "int", key: true, computed: true },
                Abbrev: { type: String, required: true, maxLength: 200 },
                Name: { type: String, required: true, maxLength: 512 }
            });

            $data.EntityContext.extend("JumpSeatDatabase", {
                Airports: { type: $data.EntitySet, elementType: Airport }
            });

            var airportDB = new AirportDatabase('http://localhost:2663/odata');
            var deferred = Q.defer();
            airportDB.onReady(function () {
                deferred.resolve(airportDB.Airports);
            });

            return deferred.promise;
        }
        var datacontext = {
            getAirports: getAirports
        };

        return datacontext;

        function log(msg, data, showToast) {
            logger.log(msg, data, system.getModuleId(datacontext), showToast);
        }

        function logError(msg, error) {
            logger.logError(msg, error, system.getModuleId(datacontext), true);
        }
        //#endregion
});

This is my airport viewmodel:

define(['services/datacontext', 'durandal/plugins/router'],
    function (datacontext, router) {
        var airports = null;// = kendo.data.ObservableArray([]);

        var activate = function () {
            var airportRes = datacontext.getAirports();
            return airportRes.then(function (airp) {
                vm.airports = airp.asKendoDataSource();
            });
        };

        var deactivate = function() {
            //airports([]);
        };

        var viewAttached = function (view) {
            //using this type of reach in to the viewModel is considered bad practice in durandal
            //$('#airportGrid').kendoGrid({
            //    dataSource: airports.asKendoDataSource({ pageSize: 10 }),
            //    filterable: true,
            //    sortable: true,
            //    pageable: true,
            //    height: 500,
            //    columns: ['Id', 'Abbrev', 'Name']
            //});
            //kendo.init($("#container"));
            kendo.bind(view, vm);//this should eventually go away the recommended ViewModelBinder code in main.js is not firing for me
        };


        var vm = {
            activate: activate,
            deactivate: deactivate,
            airports: airports,
            title: 'Airports',
            viewAttached: viewAttached
        };
        return vm;
    });

One last issue that I am seeing: It seems to me that an MVVM declared kendoui grid, bound to the view model through data-kendo-bind={source: airports)" where airports is a property of the viewmodel that was created through entities.asKendoDataSource() does not work. Somehow the grid does not show the data. Is there something extra that needs to be done?

Thanks

1

1 Answers

0
votes

My best guess is that this is a timing issue, where the Grid is binding to vm.airports while it is still null, then vm.airports = airp.asKendoDataSource(); is called after it is already bound? Perhaps try something like:

return airportRes.then(function (airp) {
    vm.airports.data(airp.asKendoDataSource().data());
});