How to close in-panel custom widget from within onOpen()?

661
4
Jump to solution
08-09-2020 09:26 AM
MichaelLev
Occasional Contributor III

In in-panel custom widget onOpen() function, if some critical config aram is empty, I output alert,

then I want to close the widget (as if someone clicked the "x" button, or as I have not clicked to open it at all).

I wrote:

            PanelManager.getInstance().closePanel(this.id + '_panel');

but it failed, maybe because I'm "inside" onOpen() ?

My questions:

1. How to nicely close in-panel custom widget programatically from within onOpen()?

2. My first lines of onPen() are:

               if (!this.isOpening) {
                     this.isOpening = true;

    Do I have to reset this.isOpening to false before I close the widget?

3. The code in WidgetManager.js id:

      if (widget.state === 'closed') {
         html.setStyle(widget.domNode, 'display', '');
         widget.setState('opened');
         try {
            widget.onOpen();
          } catch (err) {
              console.error('fail to open widget ' + widget.name + '. ' + err.stack);
           }
      }

      Should I exit onOpen() with exception and put the alert inside the Widgetmanager?

4. I wish that the widget will really cose (the icon will go back downwards.

5. I wish that I'll get the alert every time I click on the widget (not only in the first time).

Help will be greatly appreciated,

Michael

0 Kudos
1 Solution

Accepted Solutions
RobertScheitlin__GISP
MVP Emeritus

Michael,

   Sounds like it may be a race condition (timing). You should try:

setTimeout(lang.hitch(this, function () {
  PanelManager.getInstance().closePanel(this.id + '_panel');
}), 500);‍‍‍

View solution in original post

4 Replies
RobertScheitlin__GISP
MVP Emeritus

Michael,

   Sounds like it may be a race condition (timing). You should try:

setTimeout(lang.hitch(this, function () {
  PanelManager.getInstance().closePanel(this.id + '_panel');
}), 500);‍‍‍
MichaelLev
Occasional Contributor III

Dear Robert,

Thank you very much! You always save my day! It works!

Only I found that in order to get the alert when I re-open the in-panel widget,

I have to reset "isOpening" inside setTimeout:

onOpen: function () {
    if (!this.isOpening) {
        this.isOpening = true;

        let missing = [];

        // ... code lines to test parameters

        if (missing.length !== 0) {
             let errMsg = `missing config param${missing.length > 1 ? "s" : ""}: ${missing.join(", ")}`;
            alert(errMsg);

        } else {

            // code lines to do if parameteers are OK

        }

        // close widget
        setTimeout(lang.hitch(this, function () {
            this.isOpening = false;
            //PanelManager.getInstance().closePanel(this.id + '_panel');
            WidgetManager.getInstance().closeWidget(this); //best way to close
        }), 300);

    }

}, // eof onOpen()

So, now it works - thank you for explaining that closing the widget from within onOpen() creates race conditions, and for showing how to handle it.

If I may only ask, I wish to also get explanations:

  1. What is the function of "isOpening" property?
  2. What exactly is the cause of the race conditions? and how does the setTimeout handle it?
  3. Only in first opening, I got my "exact expected behaviour" -
         at first, the widget icon shifts up, then, I see the alert ,then, the widget icon shifts down
     but in all successive openings,
         first I see the alert, and only AFTER the alert, the widget icon shifts up, then shifts down.
    So, In order to always get my "exact expected behaviour"
        I had to "wrap" the whole contents of onOpen() inside an additional setTimeout (not shown in the above code).
    I assume that this is connected smehow to the same race conditions?
  4. Why if I use "closePanel(this.id + '_panel')" instead of closeWidget(this),
    I get an unwanted behaviour - 
    I do see the alert only on each 2nd click of the widget?

With appreciation,

Michael

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Michael,

1. Q: What is the function of "isOpening" property?

    A: I have not used that property before.

2. Q: What exactly is the cause of the race conditions? and how does the setTimeout handle it?

     A: Your code is requesting that the widget is to be closed before something (not sure what) is completed in the widgets code or base code is complete. Using the timeout causes the request to close to delay for so many milliseconds thus allowing what ever the race condition is to be resolved.

3. Q: ....

    A: widget shifting up and down... Are you using the launchpad theme? Again this is a timing issue and using an alert is a modal type dialog and thus blocks user interaction with the app. I normally use the jimu message dijit instead.

4. Q: Why if I use "closePanel(this.id + '_panel')" instead of closeWidget(this),
I get an unwanted behavior - I do see the alert only on each 2nd click of the widget?

    A: I am not sure. I have always had the exact opposite experience. Using closeWidget would sometimes remove the widget but leave the panel still open.

MichaelLev
Occasional Contributor III

Many thanks, Robert, for enlightening my eyes!

Michael

0 Kudos