Question

Does anyone have any experience integrating Infragistics Ingite UI controls into a Hot Towel/Durandal SPA application?

I've integrated this ig sample in a basic Hot Towel application:

http://www.infragistics.com/products/jquery/sample/grid/grid-knockoutjs-integration

It works with a simple binding, such as:

View:

<table id="grid" data-bind="igGrid: {
    dataSource: gridData, autoGenerateColumns: false,
    columns: [
        { headerText: 'Product Name', key: 'Name', dataType: 'string' }
    ]}">
</table>

VM:

define(['services/logger'], function (logger) {
    var vm = {
        activate: activate,
        title: 'Details View',
        gridData: adventureWorks // Points to ig's JSON sample data
    };

    return vm;

    //#region Internal Methods
    function activate() {
        return true;
    }
    //#endregion
});

This works fine and renders the grid. However, I get an error as soon as I add any features into the binding, eg:

<table id="Table1" data-bind="igGrid: {
    dataSource: gridData, autoGenerateColumns: false,
    features: [
        { name: 'Sorting', type: 'local' }
    ],
    columns: [
        { headerText: 'Product Name', key: 'Name', dataType: 'string' }
    ]}">
</table>

The error is "["Cannot call method '_injectGrid' of undefined", "views/details", Object]".

I'm using the jQuery.Migrate library (as ig still references 1.7 and Durandal wants 1.9), and have this to load the dependent ig scripts:

$.ig.loader({
    scriptPath: "../App/Infragistics/js/",
    cssPath: "../../Content/",
    resources: "igGrid.*,extensions/infragistics.datasource.knockoutjs.js,extensions/infragistics.ui.grid.knockout-extensions.js"
});

Incidentally I have tried using the 'traditional' jQuery (ie non-KO) API for creating the grid and I get even more problems!

Any help greatly appreciated.

Was it helpful?

Solution

I can't really provide you with a 100% suitable solution but I can tel you why you are getting this - The problems is not with knockout (or rather not because of it) - the binding of the view to the model happens before the actual view markup is attached to the document. It's loaded as a fragment I believe, so the igGrid makes an attempt to select it with jQuery and attach feature widgets to it - which obviously fails to get item that's not there yet.

I am not familiar with Hot Towel and I don't know how to get it to attach the markup first and then do Knockout bindings, so I kind of just helped it out by manually attaching the fragment to the body on beforehand in the ViewModelBinder.js:

bind: function(obj, view) {
    doBind(obj, view, function () {
        if ((view.getAttribute("data-view") == "views/details") && ($(view).parent().length == 0)) {
            $("#content").prepend(view);
        }
        ko.applyBindings(obj, view);
        if (obj.setView) {
            obj.setView(view);
        }
    });
}

And it almost works this way (moving the actual Durandal wrapper makes it twitch a little). Now I know this is not the way to go, but it is to give you an idea what's wrong. Alternatively you can add

 ko.applyBindings(settings.model, newChild);

In the entrance.js startTransition function and remove the extra prepend and the bind from above function. Still not good transition, but better.

P.S. Also noticed that when you go directly to the details view you don't wait for the loader, notice the Infragistics Loader is async and has a callback function which is how you actually wait for the Loader to be done :)

OTHER TIPS

I am not sure but because the loader's request in asynchronous the infragistics grid files may have not been loaded yet. To see if this is the problem try adding the scripts without the loader like this for example :

<link href="~/Content/IG/css/themes/infragistics/infragistics.theme.css" rel="stylesheet"type="text/css" />
<link href="~/Content/IG/css/structure/infragistics.css" rel="stylesheet" type="text/css" 
<script src="~/Scripts/IG/js/infragistics.js" type="text/javascript"></script>

you also need the knockout-grid binding javascript files. give it a try it may work.

Another idea if you want to keep the loader would be to resolve a deferred object in the loader's callback when all infra files have loaded and return that deferred object from the activate method.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top