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 theme

Web AppBuilder provides out-of-the-box themes. Use the Demo theme that comes with Web AppBuilder as an example of how to develop a theme.

The Demo theme has one panel, one widget, two styles, and two layouts as described in the following list:

NoteNote:

  • The source code of the Demo theme is in the client/stemapp/themes/DemoTheme folder. You can use the Demo theme from within the Web AppBuilder GUI. By default, it is disabled. To enable it, open the .repoignore file in client\stemapp\themes, remove DemoTheme from the file, and restart the node server.
  • Once you've created a custom theme, you can move the theme folder to any themes repository folder (client/stemapp/themes by default).

Create files for the theme

As described above, to create a theme, you need to create the necessary files under the theme folder. The following is the file structure for the Demo theme:

Theme file structure

Edit the manifest.json

The manifest.json file describes the theme’s content, and the builder reads this file to get the theme’s content. Based on the specification described above, update the manifest.json file as follows:

{
  "name": "DemoTheme",
  "panels": [
    {
      "name": "SimpleBorderPanel",
      "description": "This is a panel with a border"
    }
  ],
  "styles": [
    {
      "name": "default",
      "description": "this is default style",
      "styleColor": "red"
    },
    {
      "name": "black",
      "description": "this is black style",
      "styleColor": "#000000"
    }
  ],
  "layouts": [
    {
      "name": "default",
      "description": "this is the left layout"
    },
    {
      "name": "right",
      "description": "this is the right layout"
    }
  ],
		"platform": "HTML",
  "version": "0.0.1",
  "author": "Esri R&D Center Beijing",
  "description": "",
  "copyright": "",
  "license": "http://www.apache.org/licenses/LICENSE-2.0",
  "wabVersion": "1.1"
}

Create the panel

A panel is a UI element used to display the widget’s content. Multiple widgets can use the same panel. However, the widget does not display directly on the panel. It is put in the WidgetFrame, and the widget frame displays on the panel. One widget frame holds one widget, and one panel can contain more than one widget frame. The following image gives you a general idea of the relationships of the panel, widget frame, and widget.

Theme panel structure

Developing a panel is the same as developing a web component, which requires JavaScript, CSS, and HTML skill and knowledge. It is also beneficial to understand the dojo's layout concept and practice.

To create a panel, you need to create a class that derives from BaseWidgetPanel. If the default widget frame meets your requirements, create a frame class that derives from BaseWidgetPanel.

Life cycle functions

Just as with widget development, there are life cycle functions that you can override to interact with the AppBuilder framework.

You can override the following functions when you create a panel:

  • createFrame—This function returns the widget frame object.
  • reloadWidget—This function is called by the builder when the widget is modified.

The following life cycle functions are the same as the widget's:

  • onOpen
  • onClose
  • onMaximize
  • onMinimize
  • onNormalize
  • onActive
  • onDeactive
  • setPosition

Create SimpleBorderPanel

Because the SimpleBorderPanel is very basic, extend the BaseWidgetPanel without adding any new features. See the following code:

define(['dojo/_base/declare',
  'jimu/BaseWidgetPanel'
],
function(declare, BaseWidgetPanel) {
  return declare([BaseWidgetPanel], {
    baseClass: 'jimu-widget-panel jimu-border-panel',
  });
});

For more information about panels, see BaseWidgetPanel.js file in the client/stemapp/jimu.js folder.

Create the styles

You need to write some style (CSS) files to make the theme more attractive and have a consistent UI. In the style files, you can override the styles in jimu.css, and write the styles that your panel needs as well. Place the common styles (used by all of the styles) in the common.css file and the specific styles in the corresponding style.css files.

There should be a style named default, which is used by default from within the AppBuilder GUI.

Edit the default styles

Because the default style’s main color is red, use the following style:

.jimu-border-panel{
  border: 1px solid red;
}

Edit the black style

.jimu-border-panel{
  border: 1px solid black;
}

Create the layouts

A layout is a config template file. Although it uses the same format as the app’s config file, it may contain only a subset of the properties. For example, the default layout may contain the following:

  • widgetOnScreen—Includes all of the properties
  • map—Includes only the position property
  • widgetPool—Includes all of the properties

In the default layout, you can define on-screen widgets with the URI and position properties, or with the position property only. A widget with only the position property is called a placeholder, which allows you to add a widget during configuration.

For the non-default layouts, you can only define the position of the widget and group with either array or object as described in the following:

  • With array, you must define the position of the widget and group one by one.
  • With object, you can use the widget's URI as a key and position as a value to define the position. For the placeholder widget, since it has no URI, use ph_<i> as the key, where the <i> is the index of the placeholder. For the group, use g_<i> as the key, where the <i> is the index of the group.

In addition, you can define the layout that runs in the mobile app with the mobileLayout property. See the mobileConfig file in the App configuration reference.

When switching the layout from A to B, the positions defined in layout B automatically overrides the positions defined in layout A by the app container.. If the widget or panel's position is not defined in layout B, use layout A instead.

Finally, there should be a layout named default. This layout is used by default when the theme is selected in the AppBuilder GUI.

Edit the default layout

{
  "widgetOnScreen": {
    "panel": {
      "uri": "themes/DemoTheme/panels/SimpleBorderPanel/Panel"
    },
    "widgets": [{
      "uri": "widgets/Scalebar/Widget",
      "position": {
        "left": 25,
        "bottom": 25
      },
      "version": "1.2"
    }, {
      "uri": "widgets/HomeButton/Widget",
      "position": {
        "left": 7,
        "top": 75
      },
      "version": "1.2"
    }, {
      "uri": "widgets/Coordinate/Widget",
      "position": {
        "left": 200,
        "bottom": 20
      },
      "version": "1.2"
    }, {
      "uri": "widgets/BasemapGallery/Widget",
      "position": {
        "left": 45,
        "top": 5,
        "width": 430,
        "height": 410
      },
      "version": "1.2"
    }, {
      "position": {
        "left": 95,
        "top": 5,
        "width": 400,
        "height": 410
      }
    }, {
      "uri": "widgets/ZoomSlider/Widget",
      "visible": true,
      "position": {
        "top": 5,
        "left": 7
      },
      "version": "1.2"
    }]
  },

  "map": {
    "position": {
      "left": 0,
      "top": 0,
      "right": 0,
      "bottom": 0
    }
  }
}

Edit the right layout

{
  "widgetOnScreen": {
    "widgets": [{
      "position": {
        "left": 25,
        "bottom": 25
      }
    }, {
      "position": {
        "left": 7,
        "top": 75
      }
    }, {
      "position": {
        "left": 200,
        "bottom": 10
      }
    }, {
      "position": {
        "left": 45,
        "top": 5,
        "width": 430,
        "height": 410
      }
    }, {
      "position": {
        "right": 95,
        "top": 5,
        "width": 400,
        "height": 410
      }
    }]
  }
}

Edit the main.js file

The main.js file loads and runs when the theme loads. You can put the initialization codes in it or keep it like this: define([], function(){ });

Add i18n support

Your theme may contain some strings that you want to internationalize. Similar to the widget, you can create the string.js file in the nls folder. Refer to Add I18n support under widget development. You can also internationalize display names associated with a theme, such as _themeLabel for the theme display name, _layout _layout_[layout name] for the layout display name, and _style[style name] for the style display name.

Support RTL

There are some languages that read from right-to-left (RTL). In these languages, the app's layout should be right-to-left as well. The apps created from Web AppBuilder provide the following features for RTL support:

  • The position property configured in the app config.json file is mirrored automatically in RTL languages. For example, when the left of position property is set to 10, it is changed to the right with 10 in RTL languages.
  • Programmatically you can use CSS classes in jimu.js/css/spacing.css. When these CSS classes are applied, the page layout is changed to RTL in RTL languages.
  • The jimu-rtl class is added to the html tag. Use this class as a CSS selector to write CSS rules for RTL languages.
  • There is a global JavaScript variable, isRTL. It is automatically set to true in RTL languages.
  • Each layout has an icon named icon.png. In RTL languages, you must provide a different icon and name it icon_rtl.png.

Create a theme widget

Creating a theme widget is the same as creating a normal widget except for one additional property, isThemeWidget. This property is defined in the manifest.json file and should be set to true. The theme widget is located in the \theme name\widgets folder.

Try the Demo theme in the builder

Once you place the Demo theme in the themes folder, start the AppBuilder and create a new app. The Demo theme shows on the Themes tab.

  1. Click the Demo theme.
  2. Click the Layout icon to switch layouts.
  3. Open the BasemapGallery widget.
  4. Click the style icon to switch styles.

During development, use http://your host/webappbuilder/?id=stemapp to access your theme directly.

Best practice to create a theme

  • Use an appropriate name and icon for a theme.
  • Create more than one style and layout so users have options.
  • Put the panel’s CSS in the panel’s folder to make copying and reusing the panel easy.
  • there is no need to override all the classes in jimu.css and jimu-theme.css. Just override what you need.
  • Create more placeholders in the layout so that users can have options when configuring the app.
  • Consider how the theme looks on mobile devices when designing the theme. appInfo.isRunInMobile, a JavaScript global variable, and jimu-ismobile, a CSS class, are provided to help you develop a responsive theme. You can also use the mobileConfig property to define the layout on mobile devices.