1. Get started

  2.  Welcome
  3.  Get started
  4.  Run as a Windows service
  5.  Build your first app
  6.  Requirements
  7.  Accessibility support
  8.  Development overview
  9.  About release versions
  10.  What's new
  11.  Frequently asked questions
  12. Working with apps

  13.  Home page
  14.  Create or import an app
  15.  Edit and launch an app
  16.  Choose a theme
  17.  Select a map or scene
  18.  Add widgets
  19.  Widgets overview
  20.  Configure app attributes
  21.  Preview apps on smaller screens
  22.  Export as a template
  23.  Edit or preview template
  24.  Use URL parameters
  25.  Upgrade apps
  26. Configure 2D widgets

  27.  About widget
  28.  Add Data widget
  29.  Analysis widget
  30.  Attribute Table widget
  31.  Batch Attribute Editor widget
  32.  Basemap Gallery widget
  33.  Bookmark widget
  34.  Business Analyst widget
  35.  Chart widget
  36.  Controller widget
  37.  Coordinate widget
  38.  Coordinate Conversion widget
  39.  Cost Analysis widget
  40.  Data Aggregation widget
  41.  Directions widget
  42.  Distance and Direction widget
  43.  District Lookup widget
  44.  Draw widget
  45.  Edit widget
  46.  Emergency Response Guide widget
  47.  Extent Navigate widget
  48.  Filter widget
  49.  Full Screen widget
  50.  Geocoder widget
  51.  GeoLookup widget
  52.  Geoprocessing widget
  53.  Grid Overlay widget
  54.  Gridded Reference Graphic widget
  55.  Group Filter widget
  56.  Image Measurement widget
  57.  Home Button widget
  58.  Incident Analysis widget
  59.  Infographic widget
  60.  Info Summary widget
  61.  Layer List widget
  62.  Legend widget
  63.  Measurement widget
  64.  My Location widget
  65.  Near Me widget
  66.  Network Trace widget
  67.  Oblique Viewer widget
  68.  Overview Map widget
  69.  Parcel Drafter widget
  70.  Print widget
  71.  Public Notification widget
  72.  Query widget
  73.  Related Table Charts widget
  74.  Report Feature widget
  75.  Reviewer Dashboard widget
  76.  Scalebar widget
  77.  Screening widget
  78.  Search widget
  79.  Select widget
  80.  Share widget
  81.  Situation Awareness widget
  82.  Smart Editor widget
  83.  Splash widget
  84.  Stream widget
  85.  Suitability Modeler widget
  86.  Summary widget
  87.  Swipe widget
  88.  Threat Analysis widget
  89.  Time Slider widget
  90.  Visibility widget
  91.  Zoom Slider widget
  92. Configure 3D widgets

  93.  3DFx widget
  94.  About widget
  95.  Basemap Gallery widget
  96.  Compass widget
  97.  Coordinate widget
  98.  Daylight widget
  99.  Full Screen widget
  100.  Home Button widget
  101.  Layer List widget
  102.  Legend widget
  103.  Measurement widget
  104.  My Location widget
  105.  Navigate widget
  106.  Search widget
  107.  Share widget
  108.  Slides widget
  109.  Splash widget
  110.  Zoom Slider widget
  111. Widget development

  112.  Get started
  113.  Naming conventions
  114.  In-panel and off-panel widgets
  115.  Deploy your widget
  116.  Required files
  117.  Widget manifest
  118.  Extend BaseWidget
  119.  Required properties
  120.  Define the template
  121.  Configure the Demo widget
  122.  Add i18n support
  123.  Make widgets user-friendly
  124.  Build your first app
  125.  Communication to app container
  126.  Widget properties
  127.  Make widgets responsive
  128.  Communication between widgets
  129.  Dojo dijit
  130.  Make widgets configurable in builder
  131.  Make widgets backward compatible
  132.  Create a controller widget
  133.  Widget life cycle
  134.  Add help for your widget
  135.  Create a feature action in your widget
  136.  Provide and consume data sources in widgets
  137.  Best practices for unit testing
  138. Theme development

  139.  Theme elements
  140.  Create a theme
  141. 3D development

  142.  3D development guide
  143. Sample code

  144.  Create a custom in-panel widget
  145.  Create a ListView widget
  146.  Create a custom widget using the Report dijit
  147.  Create a new theme
  148.  Create a new style for a theme
  149.  Create a new default layout
  150.  Create a nondefault layout
  151.  Create a new panel
  152.  Create a new layout widget
  153.  Create a controller widget
  154.  Create a feature action in your widget
  155.  Send a layer to the Attribute Table widget
  156.  Open multiple widgets simultaneously
  157.  Use other libraries
  158.  Change the URL of ArcGIS API for JavaScript
  159. Deployment

  160.  Deploy your app
  161.  Use proxy
  162.  Web-tier authentication
  163.  Custom widget and theme deployment
  164.  Upgrade custom widgets and themes
  165. Framework reference

  166.  CSS framework
  167.  FeatureActionManager class
  168.  FilterManager class
  169.  LayerInfo class
  170.  LayerInfos class
  171.  LayerNode class
  172.  LayerStructure class
  173.  PanelManager class
  174.  SelectionManager class
  175.  Utils class
  176.  WidgetManager class
  177. dijit

  178.  FeaturelayerChooserFromMap class
  179.  FeaturelayerServiceBrowser class
  180.  FeatureSetChooserForSingleLayer class
  181.  Filter class
  182.  ImageChooser class
  183.  ItemSelector class
  184.  LayerChooserFromMap class
  185.  RendererChooser class
  186.  Report class
  187.  SnapShot class
  188.  SymbolChooser class
  189. JSON reference

  190.  App configuration
  191.  Map configuration
  192.  Widget configuration
  193.  Widget pool configuration
  194.  Widget on-screen configuration
  195.  Panel configuration
  196.  Group configuration
  197.  DataSource configuration
  198.  About
  199.  Analysis
  200.  Attribute Table
  201.  Basemap Gallery
  202.  Bookmark
  203.  Chart
  204.  Coordinate
  205.  Directions
  206.  Draw
  207.  Edit
  208.  Full Screen
  209.  Geocoder
  210.  Geoprocessing
  211.  Controller
  212.  Home Button
  213.  Image Measurement
  214.  Infographic
  215.  Layer List
  216.  Legend
  217.  Loading Page
  218.  Measurement
  219.  My Location
  220.  Near Me
  221.  Oblique Viewer
  222.  Overview Map
  223.  Print
  224.  Query
  225.  Report Feature
  226.  Reviewer Dashboard
  227.  Scalebar
  228.  Search
  229.  Share
  230.  Splash
  231.  Stream
  232.  Swipe
  233.  Time Slider
  234.  Zoom Slider
  235. What's new archive

  236.  What's new in version 2.23
  237.  What's new in version 2.22
  238.  What's new in version 2.21
  239.  What's new in version 2.20
  240.  What's new in version 2.19
  241.  What's new in version 2.18
  242.  What's new in version 2.17
  243.  What's new in version 2.16
  244.  What's new in version 2.15
  245.  What's new in version 2.14
  246.  What's new in version 2.13
  247.  What's new in version 2.12
  248.  What's new in version 2.11
  249.  What's new in version 2.10
  250.  What's new in version 2.9
  251.  What's new in version 2.8
  252.  What's new in version 2.7
  253.  What's new in version 2.6
  254.  What's new in version 2.5
  255.  What's new in version 2.4
  256.  What's new in version 2.3
  257.  What's new in version 2.2
  258.  What's new in version 2.1
  259.  What's new in version 2.0
  260.  What's new in version 1.3
  261.  What's new in version 1.2
  262.  What's new in version 1.1

Create a new panel

Create a modal panel to grab your user's attention on a critical step in your app. This can include alerting a user of a task that must be completed or to save important data. A modal view typically includes completion and cancel buttons that exit the view.

Create a new panel widget folder structure

Learn how to create the folder structure for your new modal panel.

Steps:
  1. Browse to the ~/client/stemapp/themes/YourTheme/panels folder and create the ModalPanel folder with the following structure:
    Panels folder structure
  2. Register ModalPanel in the panels section in the manifest.json file.
    {
      "name": "ModalPanel",
      "description": "This is a panel that appears as a modal dialog"
    }
    
  3. Import the panel’s style.css file in common.css.

    @import url("panels/ModalPanel/style.css");
    

Set the HTML template in Panel.html

Below is the HTML template for the panel.html file that is in your folder structure.

Steps:
  1. Open the Panel.html file from the ~/client/stemapp/themes/ YourTheme /panels/ModalPanel/Panel.html folder.
  2. Paste the following HTML structure that contains a title panel and a content panel into the Panel.html file:
    <div>
      <div>
      <div class="jimu-panel-title" data-dojo-attach-point="titleNode">
        <div class="widget-icon">
          <img data-dojo-attach-point="titleIconNode"/>
        </div>
        <div class="title-label" data-dojo-attach-point="titleLabelNode">
        </div>
        <div class="close-icon jimu-float-trailing" data-dojo-attach-point="closeButtonNode"></div>
      </div>
      <div class="jimu-panel-content" data-dojo-attach-point="containerNode"></div>
    </div>
    
    NoteNote:

    Some of the class names are taken from the Jimu CSS framework, which provides a set of predefined CSS styles.

Add minimal required code to Panel.js

Add some code to your new js file so it functions as expected.

Steps:
  1. Open the Panel.js file from the ~/client/stemapp/themes/ YourTheme /panels/ModalPanel folder.
  2. Copy and paste the following code into the Panel.js file:
    define(['dojo/_base/declare',
      'jimu/BaseWidgetPanel',
      'dijit/_TemplatedMixin',
      'dojo/text!./Panel.html'
    ],
    function(declare, BaseWidgetPanel, _TemplatedMixin, template) {
    
      return declare([BaseWidgetPanel, _TemplatedMixin], {
        templateString: template,
        baseClass: 'jimu-panel jimu-modal-panel',
    
        postCreate: function() {
          this.inherited(arguments);
        },
    
        startup: function() {
          this.inherited(arguments);
        }
      });
    });
    

    The following classes are required:

    • jimu/BaseWidgetPanel—The base class for a panel widget. It is located at ~/client/stemapp/jimu.js.
    • dijit/_TemplatedMixin—A Dojo mixin to compose a widget that takes an HTML template to create its DOM tree. See Create template-based widgets for more information.

Set the panel position

The ModalPanel widget has a default width of 450 pixels and height of 400 pixels, and it is placed in the center of the screen. If a position property is set in the layout configuration associated with ModalPanel, it overrides the default position properties.

Steps:
  1. Open the Panel.js file and add a new widget attribute DEFAULT_POSITION with a width property of 450 pixels and a height property of 400 pixels.

    ...
    baseClass: 'jimu-panel jimu-modal-panel',
    
    DEFAULT_POSITION: {
      width: 450,
      height: 400
    },
    ...
    

  2. Add a new method named _setPosition.
    _setPosition:function() {
    }
    
  3. Read the position configuration for the panel.
    _setPosition: function() {
      var positionConfig = this.config.panel.position;
    }
    
  4. Add code snippets to do the following:
    1. Use the default width if the width is not defined.
    2. Use the default height if the height is not defined.
    3. Horizontally center the panel if both the left and right properties are not defined.
    4. Vertically center the panel if both the top and bottom properties are not defined.
    _setPosition: function() {
      var positionConfig = this.config.panel.position;
      if (!positionConfig) return;
    
      // use default width if no width is set
      if (!('width' in positionConfig)) {
        this.domNode.style.width = this.DEFAULT_POSITION.width + 'px';
      }
      // use default height if no height is set
      if (!('height' in positionConfig)) {
        this.domNode.style.height = this.DEFAULT_POSITION.height + 'px';
      }
      // horizontally position the panel in the center
      // if no left and right properties are set
      if (!('left' in positionConfig || 'right' in positionConfig)) {
        this.domNode.style.left = '50%';
        this.domNode.style.marginLeft = -this.DEFAULT_POSITION.width * 0.5 + 'px';
      }
      // vertically position the panel in the center
      // if no top and bottom properties are set
      if (!('top' in positionConfig || 'bottom' in positionConfig)) {
        this.domNode.style.top = '50%';
        this.domNode.style.marginTop = -this.DEFAULT_POSITION.height * 0.5 + 'px';
      }
    }
    
  5. Call the _setPosition method in startup().
    startup: function() {
      this.inherited(arguments);
      this._setPosition();
    },
    
  6. In the layout config.json file, use ModalPanel as the default panel for the widget pool without defining its position property.

    "widgetPool": {
      "panel": {
        "uri": "themes/DemoTheme/panels/ModalPanel/Panel"
      }
    }
    

  7. In ArcGIS Web AppBuilder, create a new app, and select the theme that has the ModalPanel widget. Click the widget you added from the widget pool.

    It should be wrapped in a modal panel and displayed in the center of the screen as shown below.

    ModalPanel widget

  8. Add position properties to ModalPanel in the layout config.json file as shown in the following example:

    "widgetPool": {
      "panel": {
        "uri": "themes/DemoTheme/panels/ModalPanel/Panel",
        "position": {
          "top": 50,
          "bottom": 0,
          "width": 650,
         "zIndex": 101
        }
      }
    }
    

    The panel should honor these properties.

    Properties honored by the panel

Create the title pane

The widget icon, its name, and a close button are added to the title pane in this section.

Steps:
  1. Create a new method named _initTitlePane in the Panel.js file.
    _initTitlePane: function() {
    }
    
  2. Get the app’s config file.
    _initTitlePane: function() {
      var appConfig = this.config;
    }
    
  3. Populate the icon and label in the title pane.
    _initTitlePane: function() {
      var appConfig = this.config;
      if(!appConfig) return;
    
      // add icon
      if(appConfig.icon) {
        this.titleIconNode.src = appConfig.icon;
        this.titleIconNode.alt = appConfig.icon;
      } else {
        this.titleNode.removeChild(this.titleIconNode.parentNode);
      }
      // add label
      if(appConfig.label) {
        this.titleLabelNode.innerHTML = appConfig.label;
      } else {
        this.titleNode.removeChild(this.titleLabelNode);
      }
    }
    
  4. Attach the close button node to an onclick event handler in the _initTitlePane method, and make a call to the closePanel method from the panelManager instance provided by jimu/BaseWidgetPanel to close the panel.
    _initTitlePane: function() {
      ...
      // close button event handler
      var self = this;
      this.own(on(this.closeButtonNode, 'click', function() {
        self.panelManager.closePanel(self);
      }));
    }
    
    NoteNote:

    The dojo/on is to attach the onclick event. Make sure this class has been included in the class declaration.

  5. Add the following styles to the style.css file in the ModalPanel folder:
    1. Align elements in the title pane properly.
    2. Use an image as the background image of the close button.

      An image named x.png is added to the ~/client/stemapp/themes/YourTheme/panels/ModalPanel/images folder. Use any image as the close icon.

    .jimu-modal-panel .jimu-panel-title {
      padding: 10px;
    }
    .jimu-modal-panel .jimu-panel-title > * {
      display: inline-block;
      vertical-align: middle;
    }
    .jimu-modal-panel .widget-icon {
      margin-right: 10px;
    }
    .jimu-modal-panel .widget-icon img {
      height: 24px;
    }
    .jimu-modal-panel .close-icon {
      width: 24px;
      height: 24px;
      background-image: url('images/x.png');
      background-repeat: no-repeat;
      background-position: center center;
      cursor: pointer;
    }
    
  6. Call the _initTitlePane method before _setPosition in startup():
    startup: function() {
      this.inherited(arguments);
      this._initTitlePane();
      this._setPosition();
    },
    

    Your result will look similar to the following:

    Title pane with widget name, icon, and close button

Add an overlay element

Add a DOM element that covers the entire screen when the panel is open.

Steps:
  1. Add a new method named _toggleOverlay in the Panel.js file to show or hide the overlay. Also add logic to add or remove a DIV element under the panel.
    _toggleOverlay: function(isShow) {
      // create overlay
      if(!this.overlayNode) {
        this.overlayNode = document.createElement('DIV');
        this.overlayNode.className = 'jimu-modal-panel-overlay hidden';
        if(this.domNode.parentNode) {
          this.domNode.parentNode.insertBefore(this.overlayNode, this.domNode);
        }
      }
      // add/remove class 'hidden' to/from the overlay
      if(isShow) {
        domClass.remove(this.overlayNode, 'hidden');
      } else {
        domClass.add(this.overlayNode, 'hidden');
      }
    }
    
  2. Add a method named onOpen to extend the method in the jimu/BaseWidgetPanel class. It will be called when the panel is opened. Call the _toggleOverlay method and pass true as its argument.
    onOpen: function() {
      this.inherited(arguments);
      this._toggleOverlay(true);
    },
    
  3. Add a method named onClose to extend the method in the jimu/BaseWidgetPanel class. It will be called when the panel is closed. Call the _toggleOverlay method and pass false as its argument.
    onClose: function() {
      this.inherited(arguments);
      this._toggleOverlay(false);
    },
    
  4. Add CSS styles to the style overlay node in the style.css file.
    .jimu-modal-panel-overlay {
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      background: #000;
      opacity: 0.65;
      z-index: 101;
    }
    .jimu-modal-panel-overlay.hidden {
      display: none;
    }
    

    Your result will look similar to the following:

    Title pane with added DOM element

Configure the content pane to fill remaining space

The content pane does not fill the remaining space after the title pane, and the content of the widget can be cut off when it is too long. In this section, you'll position the content pane to automatically fill the remaining space.

Steps:
  1. Use the absolute position for the content pane in CSS. Open the style.css file and add the following styles:
    .jimu-panel-content {
      position: absolute;
      width: 100%;
      top: 0;
      bottom: 0;
      overflow: auto;
    }
    
    NoteNote:

    You can also use other methods to accomplish this, such as flex box, or calc() in CSS.

  2. Create a new method named _repositionContent.
    _repositionContent: function() {
    }
    
  3. Add the following code to calculate the distance between the top of the content pane and the top of the ModalPanel widget’s DOM node (this number equals the height of the title pane). Set the number to the top property in the content pane’s style.
    _repositionContent: function() {
      var newTop = this.titleNode.clientHeight;
      this.containerNode.style.top = newTop + 'px';
    }
    
  4. Call _repositionContent in the onOpen method.
    onOpen: function() {
      this.inherited(arguments);
      this._toggleOverlay();
      this._repositionContent();
    },
    

    The content pane uses all available space in the ModalPanel widget, and the scroll bar appears.

    Your result will look similar to the following:

    Title pane using available space with scroll bar