It's all about the answers!

Ask a question

How to use dojo.ready or dojo/domReady! with EWM custom presentation?


Kevin Johnson (111) | asked Nov 30 '20, 10:40 p.m.

Hello,

We've written a non-trivial custom EWM presentation for a customer which extends dijit._Widget and dijit._Templated and uses dojox.grid.DataGrid.

It has a lot of functionality which all works great except we have one issue which we are unable to solve. Sometimes the DataGrid does not render on the EWM work item tab. Sometimes we need to click the EWM work item refresh icon to get it to load. Sometimes it won't load at all - especially if go to a work item we had accessed prior to the current work item we are working on.

It seems like a classic case of needing dojo.ready or dojo/domReady! - but I cannot get these to help at all.

1 - Where in our JS code would be put the dojo.ready? I've surrounded the following code with dojo.ready but with no success:
grid.placeAt();   
grid.startup();

2 - Can I use dojo/domReady! with code that is not loaded with AMD? Do I have to use AMD compatible code?

3 - Sometimes with firefox or chrome debugger I can that the grid (table) HTML code is there. But it is display=none

4 - Is any of this well-documented and I just haven't found it yet.

5 - I've looked at existing EWM JS code such as
- com.ibm.team.rtc.foundation.web.ui.views.tags.DecoratedTagWidget.js
- com.ibm.team.rtc.foundation.web.ui.views.tags.explorer.ItemBrowser.js
these do not use dojo.ready or dojo/domReady!

Any / all help is appreciated.

Thanks,
Kevin

2 answers



permanent link
Lawrence Smith (3764) | answered Dec 02 '20, 11:27 a.m.
JAZZ DEVELOPER
edited Dec 02 '20, 11:29 a.m.
Hello... The workitem code does not use dojo DataGrid. It also does not use the domReady calls of base dojo.  Here are some things to try:

1) Check that the require statements include all the elements referenced.  Sometimes if a require is not included then the order in which a component is loaded will determine if a non-specified required component is already loaded or missing, meaning that it will not render on first load but would render on refresh.  The fix is to add all the require statements.

2) Use a setTimeout to defer loading of the grid until the target element is available in the dom. Something like (untested psuedocode)...
postCreate(): function {
...
waitAndRender(6000); // * 100 ms
...
}

waitAndRender: function(count) {
     if (count<=0) {
          console.log("Page not loaded for...");
          return; // fail
     }
     window.setTimeout(dojo.hitch(this, function() {
            if (this.elementLoaded()) {
                 this.doRenderGrid();
            } else {
                  this.waitAndRender(count-1); // stop after so many tries
            }
        }), 100);
}

3) Use page lifecycle events. This is a hack since it uses internal events but there are a few events (see EventTopics.js) that are published...
// EventTopics.WORKITEM_PAGE_LOADED= "rtc/workitems/page/loaded"
// EventTopics.WORKITEM_VIEW_CHANGED= "workitem/view/changed"
var handle= dojo.subscribe("rtc/workitems/page/loaded", this, doRenderGrid);

// remember in the destroy method or sooner to unsubscribe
onDestroy... dojo.unsubscribe(handle).

4) If the widget itself is not loading, try a super simple version that just renders a text div or something to see that it is loading, then add in the required components until it fails.

For further analysis we would need to look at the code including the requires and postCreate, and how the contribution is specified.

Regards,
Lawrence



Comments
Kevin Johnson commented Dec 02 '20, 11:29 p.m. | edited Dec 02 '20, 11:34 p.m.
Hello Lawrence,

Thank you for your help. Here is my latest post with more details:

1) The require statements look complete.
2) I tried setTimeout to defer loading of the grid but that didn't help.
3) I tried the page lifecycle events.
4) Text does get displayed in the <div>. I tried just DataGrid with no data (only headers ) but same result.

In summary, it all works great until I revisit a WI that I have visited before. When I navigate to a new WI then the Widget constructor and postCreate are called - and it all works great. But when I visit a previous WI (that worked great the first visit) then the DataGrid does not render. It will render if I then hit the yellow refresh since it at this points calls the constructor and postCreate. It all fails when the current Widget instance is reused against a previous WI.




Lawrence Smith commented Dec 04 '20, 12:58 p.m.
JAZZ DEVELOPER

This is a rendering problem with the dojo.DataGrid which is not used in Work Items.  the DataGrid may require dojo calls to destroy the old one and recreating it when the widget is in view.  Or there is a dojo version or library incompatibility.  I searched for DataGrid and found it referenced in dojox.grid library. Maybe this is being overlaid with a dojo library that does not have DataGrid.


permanent link
Lawrence Smith (3764) | answered Dec 04 '20, 1:50 p.m.
JAZZ DEVELOPER

Please keep the post to one question thread.


DataGrid may be designed to be a singleton. The source code for it shows it uses some kind of store. Be sure the store is cleared and refreshed when switching items. Debug into DataGrid and see what it is doing. use the ?debug=true#action= to look at the code. 

If the class itself is somehow being overwritten... then maybe try not using DataGrid or copy the DataGrid class locally and rename it and use that to see if it is some kind of dojo conflict.


Comments
Kevin Johnson commented Dec 04 '20, 3:40 p.m.

Hello Lawrence, thank you for your help. I've been reading and re-reading your comments above and still trying to understand what I need to change/fix.

The widget/DataGrid always fails in only one specific use case:
- If the user goes back to visit a WI that they had visited earlier in the EWM session then the widget is not rendering the DataGrid.

I have observed the following behavior:
- When a user visits a new WI during a session then the widget constructor() and postCreate() functions are called. This is expected.
- When a user visits a WI that they have previously visited during the session then the constructor() and postCreate() functions are NOT called. So, for example, assume a user navigates to WI 200, then to WI 500, and then back to WI 200. The instance of the widget that is being used for the 2nd visit to WI 200 is the one that was instantiated when the user went to WI 500. And for some unknown reason my JS code fails to placeAt() the DataGrid to the HTML template (from _Templated).

Any thoughts? Thank you!

-Kevin


Lawrence Smith commented Dec 09 '20, 1:57 p.m.
JAZZ DEVELOPER
It looks like the DataGrid is either implemented as a singleton or there is a problem in the usage such as passing the same store to two DataGrid. When you switch work items it may be that the prior DataGrid has to be removed then a new one added to the new work item, and a new store provided.  Perhaps publishing an event that is subscribed by the widget to move it to the work item when it is presented. I have not looked at this component.



Lawrence Smith commented Dec 09 '20, 1:58 p.m.
JAZZ DEVELOPER

Looking at the SubscribersPart there is a refresh on showWidget and when the working copy changes. The showWidget is called automatically and the work item change is subscribed to (and unsubscribed on destroy):
showWidget: function() {
            if(this._isInitialized) return;
            this._isInitialized = true;
            this.refresh();
        },



Lawrence Smith commented Dec 09 '20, 1:59 p.m.
JAZZ DEVELOPER
The work item change is subscribed to (and unsubscribed on destroy):

_handleWorkingCopyChange: function(parms) {
            this.refresh();
        }
---
this.workingCopy.addListener({
                    path: path,
                    event: "onchange",
                    listener: this,
                    functionName: "_handleWorkingCopyChange"
                });   

Lawrence Smith commented Dec 09 '20, 1:59 p.m.
JAZZ DEVELOPER

Is the class inheritance correct?  The documentation shows...

The class attribute references either a subclass PresentationPart or AttributePart, depending of whether needsAttribute is false or true. The id is references as kind from the process specification.

The contribution in the plugin.xml looks similar to this:
<editorPresentation
         id="com.ibm.team.workitem.kind.workItemList"
      widget="com.ibm.team.workitem.web.ui.internal.view.editor.parts.WorkItemListPart"
         needsAttribute="true" >
      </editorPresentation>

Your answer


Register or to post your answer.