Adding custom option to Layer List widget context menu?

854
5
Jump to solution
12-23-2019 01:36 PM
EricRuberson1
New Contributor III

Question 1: What does clazz.create in PopupMenuInfo.js actually do (line 411)? I think I understand the rest of the functions of that javascript file, but not that one.

Question 2: Do I need to add anything to clazz.create if I am adding a custom context menu item? It looks like it is seperate lists of menu items, so I probably do, but I am unsure.

Question 3: Do I need to modify anything outside of PopupMenuInfo.js in order to succesfully add a new item to the context menu?

Backstory:

I'm fairly positive I'm using the Layer List widget and one of my coworkers renamed it to Table of Contents.

I want to do the opposite of what was asked in this question: https://community.esri.com/thread/115128 

I want to add an item to the context menu. It will ultimately be grayed out if another widget isn't loaded, but if that widget is loaded, will run code that makes the other widget do things.

So I think I need to add stuff:

  1. in _initCandidateMenu Items (line 94)
  2. in getDeniedItems (line 176)
  3. in onPopupMenuClick (line 269)
  4. a new function probably around line 410, which will be called by the modifications made in bullet 3
  5. I am not sure what, if anything, I need to do in clazz.create.

I've attached the version of PopupMenuInfo.js we are using, in the off chance it's different than the 'standard' one out there.

0 Kudos
1 Solution

Accepted Solutions
RobertScheitlin__GISP
MVP Emeritus

Eric,

1.  The clazz.create is the method that gets invoked when the PopupMenuInfo.create is called (you can see this in the PopupMenu.js > openDropMenu method). You will notice that the PopupMenuInfo.js actually returns clazz. So clazz and PopupMenuInfo.js are one and the same.

2.  Yes. Add your item to all layer types that you are interested in.

3.  No.

So I think I need to add stuff:

1. Yes

2. Yes if you only want this item to be visible if the widget is opened

3. Yes

4. Yes

5. Nope

View solution in original post

5 Replies
RobertScheitlin__GISP
MVP Emeritus

Eric,

1.  The clazz.create is the method that gets invoked when the PopupMenuInfo.create is called (you can see this in the PopupMenu.js > openDropMenu method). You will notice that the PopupMenuInfo.js actually returns clazz. So clazz and PopupMenuInfo.js are one and the same.

2.  Yes. Add your item to all layer types that you are interested in.

3.  No.

So I think I need to add stuff:

1. Yes

2. Yes if you only want this item to be visible if the widget is opened

3. Yes

4. Yes

5. Nope

EricRuberson1
New Contributor III

Robert,

I have tried following along with the tutorials for communication between widgets to try and get my new menu option to send data to another widget after opening it. I can open that widget.  I can't seem to call that widget's functions, and that doesn't seem to be supported. So I tried to use the Publish/onReceiveData option, but that doesnt seem to work because PopupMenuInfo.js is not designed to work with it.

The communication between widgets example uses

define(['dojo/_base/declare', 'dojo/_base/lang', 'jimu/BaseWidget'],
function(declare, lang, BaseWidget) {
  return declare([BaseWidget], {‍‍‍

to open it's script.

there is no equivalent to "return declare" in the PopupMenuInfo.js, since its returning clazz, and my attempts to insert BaseWidget references don't work.

I tried changing the "var clazz = declare([],{" line to "var clazz=declare([BaseWidget],{" along with the corresponding jimu/BaseWidget tag in the prior line, but that results in errors occurring outside of the script. I don't understand why it doesn't work. Per the dojo dojo/_base/declare — The Dojo Toolkit - Reference Guide API, it seems like it should, but it errors out on one of the API scripts.

I even tried turning it into a local require statement (per this doc: Defining Modules - Archived Tutorial - Dojo Toolkit  , the second example under Conditionally-Requiring Modules), as in my code below, but the error just says publishData is not a function.

_onRunReport: function(evt) { //New Function in PopupMenuInfo.js
      console.log("Run Report selected from context menu");
      var reportWidget = this.layerListWidget.appConfig.getConfigElementsByName("modIdentify")[0];
      var wm = WidgetManager.getInstance();
      
      console.log('Report run on: '+(this._layerInfo.id ||'undefined')); //confirmed pulls different layer ids when different layers selected
      //console.log(this._layerInfo||'undefined'); //full layer info

      
      require([ 'jimu/BaseWidget' ], function(BaseWidget){ //no longer creates an error outside of the script
        if (wm.getWidgetByLabel(reportWidget.id)==null){ //Open widget if not loaded
          wm.triggerWidgetOpen(reportWidget.id)
          .then(lang.hitch(this, function() {
            
            ////try 1: didnt work
            //would ideally call modIdentify's onAddedLayer function and pass it the geometry from the current layer, but this didnt work.
            //Cannot find evidence this kind of functionality is supported.
            //this.reportWidget.onAddedLayer(this._layerInfo);
   
            //Try 2: This should work but browser doesnt think publishData is a function
            this.publishData({
              message: this._layerInfo
            });
          }));
  
        }
        else{ // widget already loaded
          //Copy of whatever works above.
          //this.modIdentify.onAddedLayer(this._layerInfo);
          this.publishData({
            message: this._layerInfo
          });
        }
      });
},‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

I'm at a loss of what to do at this point. I don't know why it's breaking. I think I will have to work on this from the viewpoint of the other widget, and add a listener to it for this event click, but that's essentially what the Publish Data thing is supposed to do.

I've attached my full modified version of the script. Code above starts around line 407, although I've removed some commented lines and added further annotation to the version above.

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Eric,

  You should be able to call a method directly in the widget. I do this in many of my widgets.

      var reportWidget = this.layerListWidget.appConfig.getConfigElementsByName("modIdentify")[0];
      WidgetManager.getInstance().triggerWidgetOpen(reportWidget.id)
      .then(function(myWidget) {
        myWidget.callSomeMethod(someParameter);
      });‍‍‍‍‍‍‍‍‍
EricRuberson1
New Contributor III

Robert, that worked, thank you so much! Now my errors are being made within the reportWidget's widget.js file instead of PopupMenuInfo.js, because I'm not sending the right thing over yet. Progress!

Below is the adapted version of the code below for any future researchers.

//new function in PopupMenuInfo.js, runs when new custom menu option clicked
_onRunReport: function(evt) {
      var reportWidget = this.layerListWidget.appConfig.getConfigElementsByName("modIdentify")[0];
      var wm = WidgetManager.getInstance();
      
      if (wm.getWidgetByLabel(reportWidget.id)==null){ //reportWidget is not yet open
        wm.triggerWidgetOpen(reportWidget.id)
        .then(function(reportWidget) {
          reportWidget.onAddedLayer(this._layerInfo);
        });
      }
      else{ //reportWidget is already open
        reportWidget.onAddedLayer(this._layerInfo);
      }‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
},‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
0 Kudos
EricRuberson1
New Contributor III

Thank you sir. I did get the menu option to appear. Now I just need to make it work!

0 Kudos