Event Handler for LayerList widget item toggle in 4.9

2330
4
02-20-2019 10:22 AM
Jay_Gregory
Occasional Contributor III

I can't quite grasp how to attach an event handler to the LayerList widget so that each time a user clicks (toggles) a layer, I can run a custom function. I want to attach this to every layer, not just individual ones...

I tried 

const layerList = new LayerList({
 view: mapView,
 container: 'layerlist'
 });
 layerList.viewModel.on('trigger-action', myCustomFunction);‍‍‍‍‍

I also tried it with just

layerList.on('trigger-action', myCustomFunction)

Any tips here?

0 Kudos
4 Replies
RobertScheitlin__GISP
MVP Emeritus

Jay,

  The trigger-action is only going to occur when the user clicks the list item menu (i.e. the three dots)

layerList.on("trigger-action", function(event) {
  ...
});

You use the LayerList listItemCreatedFunction property when you want to do something for each item that is created in the Layerlist.

Here is a sample that when you toggle the parent item the console.logs it's visibility:

<!DOCTYPE html>
<html>
<head>

  <meta charset="utf-8">
  <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">

  <title>LayerList widget with actions - 4.10</title>

  <style>
    html,
    body,
    #viewDiv {
      padding: 0;
      margin: 0;
      height: 100%;
      width: 100%;
      overflow: hidden;
    }
  </style>

  <link rel="stylesheet" href="https://js.arcgis.com/4.10/esri/css/main.css">
  <script src="https://js.arcgis.com/4.10/"></script>

  <script>
    require([
      "esri/Map",
      "esri/views/MapView",
      "esri/layers/GroupLayer",
      "esri/layers/MapImageLayer",
      "esri/widgets/LayerList"
    ], function(
      Map, MapView, GroupLayer, MapImageLayer, LayerList
    ) {

      // Create layer showing sample data of the United States.
      var USALayer = new MapImageLayer({
        url: "http://sampleserver6.arcgisonline.com/arcgis/rest/services/USA/MapServer",
        title: "US Sample Data"
      });

      // Create layer showing sample census data of the United States.
      // Set visibility to false so it's not visible on startup.
      var censusLayer = new MapImageLayer({
        url: "http://sampleserver6.arcgisonline.com/arcgis/rest/services/Census/MapServer",
        title: "US Sample Census",
        visible: false
      });

      var map = new Map({
        basemap: "dark-gray",
        layers: [USALayer, censusLayer]
      });

      // Add the map to a MapView
      var view = new MapView({
        center: [-98.5795, 39.8282],
        zoom: 5,
        container: "viewDiv",
        map: map
      });

      // Creates actions in the LayerList.
      var uniqueParentItems = [];

      function defineActions(event) {
        var item = event.item;
        if(!item.parent){
          //only add the item if it has not been added before
          if(!uniqueParentItems.includes(item.title)){
            uniqueParentItems.push(item.title);
            item.watch("visible", function(event){
              console.info(event);
            });
          }
        }
      }

      view.when(function() {
        var layerList = new LayerList({
          view: view,
          // executes for each ListItem in the LayerList
          listItemCreatedFunction: defineActions
        });

        // Add widget to the top right corner of the view
        view.ui.add(layerList, "top-right");
      });
    });
  </script>

</head>

<body>
  <div id="viewDiv"></div>
</body>

</html>
Jay_Gregory
Occasional Contributor III

Okay, this kind of works for my purposes.  However, I've been having a hard time with the watch handlers.  Sometimes the function (in your example it's defineActions) runs 5 times for adding a single layer - and I haven't really been able to figure out how to only set a watcher once on the top level.  The uniqueParentItems doesn't always work - plus sometimes the item.title is "Layer" until the layer is actually loaded and able to get the title (since I'm loading layers from the portal).  It's making my head spin....

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Strange the item.parent and uniqueParentItems was working for me.

0 Kudos
VladS
by
New Contributor

RobertScheitlin__GISP,
this solution works for me, tnx. But listItemCreatedFunction removes item.panel.open switcher. Is it possible to keep the item.panel.open switcher and add an observer to it?

----------

I've found it!

Only add to defineActions next code:

 

item.panel = {
 content: 'legend',
 open: true,
};
item.panel.watch('open', function (event) {
  console.info(event);
});

 

 

0 Kudos