Integrate the koGrid with the Durandal/HotTowel template
Asked Answered
A

3

9

I work on an asp.net solution with the Durandal template.

I try to use the koGrid (https://github.com/Knockout-Contrib/KoGrid) which is compatible with knockout. When inserting this grid in a test page managed by Durandal, it doesn't work: the grid seems to be there but not correctly displayed.

We noticed that if we resize the window, then the grid adjust correctly.

Does anyone already succeed integrate this koGrid in a Durandal/HotTowel template?

Steps to reproduce the problem:

  • Create a new ASP.NET MVC project and choose the Durandal template
  • Add the koGrid in the project (available in Nuget)
  • Place this grid on a view and add dummy data
  • Run and display the view containing the grid

Here is a zip containing a little ASP.NET MVC project to reproduce the problem: https://www.dropbox.com/s/15rphyhkqp1h8py/KOGrid-HotTowelTemplate.zip

Thanks for your help.

Adolfo answered 28/3, 2013 at 11:27 Comment(1)
Hi Bronzato. Well I can tell that I know what the problem is, but haven't had time yet to formulate a workaround. The KOGrid relies on the CSS property to apply width/height attributes that you correctly supplied via your app.css file. However, when KOGrid does its binding in Durandal/HotTowel, the KOGrid element is not yet part of the DOM and does not get its properties set. This leaves the outer width/height attributes on the DIV wrapper set to 0px, and cascades down as the KO binding applied for KOGrid is depending on it.Chiachiack
C
4

This should be considered a workaround only! Applies to Durandal.Core 1.2 with koGrid-2.1.1.js. If either changes to fix this behavior, I will update the post.

Add a viewAttached() function in your viewmodel (and be sure to add it to your object literal) like so:

function viewAttached() {
    logger.log('Home View Attached', null, 'home', true);
    $(window).trigger('resize');
    return true;
}

The viewAttached function occurs after the composition binding, and the trigger will cause the koGrid to update its width/height observables. koGrid listens for this event.

NOTE: There are still CSS conflicts with the HotTowel template that you will need to resolve. The SPA uses a font-size of 18px on the body tag. Also the panel checkboxes should be hidden, a possible conflict with the Bootstrap CSS.

Chiachiack answered 2/4, 2013 at 7:21 Comment(2)
Thank you very much. We'll try it asap and keep you in touch.Adolfo
viewAttached is no more, so use attached attached: function() { $( window ).trigger( 'resize' ); return true; }Catchpole
A
2

The previous solution will ensure the grid displays, however, sorting does not work for me at least. As mikekidder commented above the core of the problem is that "when KOGrid does its binding in Durandal/HotTowel, the KOGrid element is not yet part of the DOM". You need to ensure that KOGrid does not do its binding until after the view is attached. This can be achieved as follows:

1) Add a new observable to the viewmodel to hold a boolean value for whether the view has been attached or not by durandal:

isAttachedToView = ko.observable(false)

and expose it

isAttachedToView: isAttachedToView

2) Up date it to be true when the viewAttached function callback is invoked:

function viewAttached() {
    isAttachedToView(true);
    logger.log('viewAttached');
    $(window).trigger('resize');
    return true;
}

3) Surround your HTML with a ko if statement to ensure that bit of HTML is not evaluated (i.e. kogrid does not do its binding) until after the view is attached:

<!-- ko if: isAttachedToView() -->
    <div data-bind="koGrid: { data: ...

<!-- /ko -->

4) Reset isAttachedToView to be false on deactivating view

function deactivate() {
    isAttachedToView(false);
}

And expose this:

deactivate: deactivate
Argus answered 28/6, 2013 at 11:55 Comment(7)
The line: $(window).trigger('resize'); is actually redundant as the code now ensures that kogrid doesn't do it's binding until the fragment is in the DOM. Would be interested to hear if this works for you.Argus
Rob Eisenberg the creator of Durandal replied to me via his google group: groups.google.com/forum/#!topic/durandaljs/h3ggF3VQG0E It seems that when Durandal 2.0 comes out it will have a more elegant built in solution for this kind of thing. Until that arrives the above should do the business.Argus
I tested and I confirm you that this trick is working pretty well, no need of $(window).trigger('resize')Adolfo
Tim, I would like to know if you noticed the following problem with koGrid used inside Durandal: you take a fresh Durandal solution, you install the koGrid package from nuget for example (named Knockout.koGrid), you followed the Getting started like here github.com/ericmbarnard/KoGrid/wiki/Getting-Started (eventually you add more rows, to have a total of 6 rows) and you run it. You resize the window to have the grid refreshed and here is the problem I noticed: the 6 rows are not all visible, only the first one. To have all rows visible, ... (see next comment)Adolfo
... I had to find the kgViewport inside html code of koGrid (F12 Developper tools) and comment the css for height: 20px then I can seel all my rows on my koGrid. Thanks.Adolfo
Yes I had to override some of the kogrid CSS as follows: .kgTopPanel { background-color: #ffffff; border: 1px solid rgb(212,212,212); } .kgHeaderCell:last-child { border-right: none; } .kgHeaderContainer, .kgViewport { height: 100% !important; width: 100% !important; } .kgViewport { overflow-y: hidden; border: 1px solid rgb(212,212,212); border-top: none; height: 100% !important; } .kgViewport:focus { outline: none !important; } .kgCell:last-child { border-right: none; } .kgViewport .kgRow:hover .kgCell { background-color: #f5f5f5; }Argus
If you are composing in a fragment that contains a kogrid and you have set cacheViews:true, you will also need to set alwaysAttachView:true (durandaljs.com/documentation/Composition) otherwise "viewAttached will only be called the first time the view is shown". If any of this is useful feel free to up vote :)Argus
B
0

This update applies to Durandal 2.x

Starting with Durandal 2.0, there is a way to specify bindings that should be deferred until the composition complete.

For kogrid to work correctly, all that's needed is to execute this line of code as part of the Durandal framework initialization:

composition.addBindingHandler('koGrid');

The composition variable in this example is a reference to the Durandal composition module.

See the documentation for more information: http://durandaljs.com/documentation/Interacting-with-the-DOM.html

Bouley answered 11/7, 2014 at 11:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.