List view custom widget for web app builder

3538
11
07-24-2017 09:35 AM
NiloufarHosseini_Pour
New Contributor

list view custom widget

Create a ListView widget—Web AppBuilder for ArcGIS (Developer Edition) | ArcGIS for Developers 

has a bug in the code. I think the problem is at step 8 and 9. since layerInfosObj is undefined.  and there is a problem in settings. Would you please provide me with the final working code?

Thank you very much.

11 Replies
KenBuja
MVP Esteemed Contributor

What is the list of modules in the define and the list of arguments in the function from step 6? Do their orders match?

The abc’s of AMD | ArcGIS Blog 

0 Kudos
niloufarhosseini_pour1
New Contributor

I copied as the instruction:

define([ 'dojo/_base/declare',

'jimu/BaseWidgetSetting',

'dojo/_base/lang',

'dojo/_base/array',

'dijit/_WidgetsInTemplateMixin',

'dijit/form/Select',

'jimu/LayerInfos/LayerInfos' ],

function(declare, BaseWidgetSetting, lang, array, _WidgetsInTemplateMixin, Select, LayerInfos) {

but I get an error mentioning layerInfosObj  is undefined.

0 Kudos
RickeyFight
MVP Regular Contributor

I have yet to be able to get their sample code to work. 

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

All,

   Here are my fixes commented in the code for this sample:

jsong-esristaff

Settings.js:

///////////////////////////////////////////////////////////////////////////
// Copyright © 2014 - 2016 Esri. All Rights Reserved.
//
// Licensed under the Apache License Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
///////////////////////////////////////////////////////////////////////////

define([
    'dojo/_base/declare',
    'jimu/BaseWidgetSetting',
    'dojo/_base/lang',
    'dojo/_base/array',
    'dijit/_WidgetsInTemplateMixin',
    'dijit/form/Select',
    'jimu/LayerInfos/LayerInfos'
  ],
  function(declare, BaseWidgetSetting, lang, array, _WidgetsInTemplateMixin, Select, LayerInfos) {

//Fix 1 add ', _WidgetsInTemplateMixin' to the declare array
    return declare([BaseWidgetSetting, _WidgetsInTemplateMixin], {
      baseClass: 'jimu-widget-listview-setting',

      postCreate: function() {
        //the config object is passed in
        this.setConfig(this.config);
      },

      setConfig: function(config) {
        // Update header text
        this.headerTextNode.value = config.widgetHeaderText;

        // Get all feature layers from the map
        var layerInfosObj = LayerInfos.getInstanceSync();
        var infos = layerInfosObj.getLayerInfoArray();
        var options = [];
        array.forEach(infos, function(info) {
          if(info.originOperLayer.layerType === 'ArcGISFeatureLayer') {
            options.push({
              label: info.title,
              value: info.id
            });
          }
        });
        this.layerSelect.set('options', options);
//Fix 2
        if(config.layerId){
          this.layerSelect.set('value', config.layerId);
        }
//End Fix 2
        this.layerSelect.on('change', lang.hitch(this, function(value) {
          var selectedLayer = layerInfosObj.getLayerInfoById(value);
          if(selectedLayer) {
            var fieldOptions = array.map(selectedLayer.layerObject.fields, function(field) {
              return {
                label: field.alias || field.name,
                value: field.name
              }
            });
            this.thumbnailSelect.set('options', fieldOptions);
            this.titleSelect.set('options', fieldOptions);
//Fix 3
            if(config.thumbnailField){
              this.thumbnailSelect.set('value', config.thumbnailField);
            }
            if(config.titleField){
              this.titleSelect.set('value', config.titleField);
            }
//End Fix 3
          }
        }));
      },

      getConfig: function() {
        //WAB will get config object through this method
        return {
//Fix 4
          widgetHeaderText: this.headerTextNode.value,
//End Fix 4
          layerId: this.layerSelect.get('value'),
          thumbnailField: this.thumbnailSelect.get('value'),
          titleField: this.titleSelect.get('value')
        };
      }
    });
  });
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Widget.js:

define(['dojo/_base/declare',
    'jimu/BaseWidget',
    'dojo/_base/lang',
    'dojo/Deferred',
    'dgrid/OnDemandList',
    'dgrid/Selection',
    "dojo/store/Memory",
    "esri/tasks/query",
    "esri/symbols/SimpleMarkerSymbol",
    "esri/symbols/SimpleLineSymbol",
    "esri/symbols/SimpleFillSymbol"
  ],
  function(declare, BaseWidget,
    lang, Deferred,
    OnDemandList, Selection, Memory,
    Query, SimpleMarkerSymbol, SimpleLineSymbol, SimpleFillSymbol) {
    //To create a widget, you need to derive from BaseWidget.
    return declare([BaseWidget], {
      baseClass: 'jimu-widget-listview',

      postCreate: function() {
        this.inherited(arguments);
        this.headerNode.innerHTML = this.config.widgetHeaderText;
        this.featureLayer = this.map.getLayer(this.config.layerId);

        var highlightSymbol;
        switch(this.featureLayer.geometryType) {
          case 'esriGeometryPoint':
            highlightSymbol = new SimpleMarkerSymbol(SimpleMarkerSymbol.STYLE_CIRCLE, 20, null, '#e74c3c');
            break;
          case 'esriGeometryPolyline':
            highlightSymbol = new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, '#e74c3c', 3);
            break;
          case 'esriGeometryPolygon':
            highlightSymbol = new SimpleFillSymbol(SimpleFillSymbol.STYLE_SOLID,
              new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, '#fff', 2),
              '#e74c3c');
            break;
        }
        this.featureLayer.setSelectionSymbol(highlightSymbol);

        this.createList();
      },

      getDataStore: function() {
        var def = new Deferred();
        var layer = this.map.getLayer(this.config.layerId);
        // Query features
        var query = new Query();
        query.returnGeometry = false;
        query.outFields = ["*"];
        query.where = '1=1';
        layer.queryFeatures(query, lang.hitch(this, function(featureSet) {
          var featureSetRemapped = [];
          for(var index in featureSet.features) {
            var feature = featureSet.features[index];
            featureSetRemapped.push({
              'id': feature.attributes[this.featureLayer.objectIdField],
              'title': feature.attributes[this.config.titleField],
              'thumbnailImg': feature.attributes[this.config.thumbnailField]
            });
          }

          def.resolve(new Memory({
            data: featureSetRemapped
          }));
        }));

        return def;
      },

      createList: function() {
        this.getDataStore().then(lang.hitch(this, function(datastore) {
          var list = new(declare([OnDemandList, Selection]))({
            'store': datastore,
            'selectionMode': 'single',
            'renderRow': lang.hitch(this, function(object, options) {
              return this._createListItem(object);
            })
          }, this.ListNode);
          list.startup();
          list.on('.dgrid-row:click', lang.hitch(this, function(evt) {
            var row = list.row(evt);
            var query = new Query();
            query.objectIds = [row.data.id];
//Fix 1            
            this.featureLayer.selectFeatures(query, esri.layers.FeatureLayer.SELECTION_NEW, lang.hitch(this, function(result) {
//End Fix 1
              if(result.length) {
                var feature = result[0],
                  newMapCenter,
                  geometry = feature.geometry,
                  extent = geometry.getExtent(),
                  shape = feature.getShape();
                if(extent && extent.getCenter) {
                  newMapCenter = extent.getCenter(); // polygon & polyline
                } else {
                  newMapCenter = geometry; // point
                }
                this.map.centerAt(newMapCenter); // move to the feature
                if(shape) shape.moveToFront(); // move the feature to front
              }
            }));
          }));
        }));
      },

      _createListItem: function(featureObj) {
        var listItemRoot = document.createElement('DIV');
        listItemRoot.className = 'list-item';
        if(featureObj) {
          var thumbnailImgWrapper, thumbnailImg, listItemTitle;
          // Create thumbnail
          if(featureObj.thumbnailImg) {
            thumbnailImgWrapper = document.createElement('div');
            thumbnailImgWrapper.className = 'thumbnail-wrapper';
            thumbnailImg = document.createElement('img');
            thumbnailImg.src = featureObj.thumbnailImg;
            thumbnailImgWrapper.appendChild(thumbnailImg);
            listItemRoot.appendChild(thumbnailImgWrapper);
          }
          // Create title
          if(featureObj.title && typeof featureObj.title === 'string') {
            listItemTitle = document.createElement('H4');
            listItemTitle.innerHTML = featureObj.title;
            listItemRoot.appendChild(listItemTitle);
            if(thumbnailImg)
              thumbnailImg.alt = featureObj.title;
          }
        } else {
          listItemRoot.innerHTML = 'NO DATA AVAILABLE';
        }

        return listItemRoot;
      }
    });
  });
Jianxia
Esri Regular Contributor

Robert,

Thanks for the fixes. We will look into it. cc to YMa-esristaff

Jianxia

0 Kudos
RickeyFight
MVP Regular Contributor

Even with Roberts fixes I cannot get this widget to work. 

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Rickey,

   Strange I have no problem (after my changes). You may want to carefully re-check each step of the tutorial.

RickeyFight
MVP Regular Contributor

Robert,

I will delete everything and start over and see if I can get it right. 

Update:

I got it working. Thank you Robert Scheitlin, GISP‌ 

BTW, you cannot just copy and paste in your code. The ending parentheses and brackets in widget.js can be confusing. 

suggestion:

  return listItemRoot;
      }
more code or ...
    });
  });
0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Rickey,


  Strange I thought I copied the complete Widget.js code when I posted it. I will have to check that but it should have just copied and pasted.

0 Kudos