Skip To ContentArcGIS for DevelopersSign In Dashboard

Note: Support for 3D on mobile devices may vary, view the system requirements for more information.

This sample shows how to use Riot with ViewModels to create a custom widget experience. Specifically, it demonstrates how to use the ZoomViewModel to create a custom zoom buttons Riot "tag".

1. Set up Riot

First, you need to load the necessary libraries, including Riot's in-browser compiler which transforms custom tags into JavaScript. For your own projects you can choose to compile Riot tags in several different ways.

<!-- load riot.js and its compiler -->
<script src="//"></script>
<!-- load Esri JSAPI -->
<script src=""></script>

2. Create a simple map and view

Create a simple map and add it to either a MapView or a SceneView. If you are unfamiliar with views or how to create a basic map see the following resources:

var map = new Map({
  basemap: "topo"

var view = new MapView({
  container: "viewDiv",
  map: map,
  zoom: 10,
  center: [-100.33, 25.69],
  ui: {
    components: ["attribution"]
  constraints: {
    minZoom: 7,
    maxZoom: 12

3. Create a custom Riot tag

Create a custom Riot tag (i.e. widget, component, etc.) with an HTML template and JavaScript logic. For more information on this, see the Riot documentation. To display the MapView's or SceneView's current scale and zoom values, watch those view properties for changes and then apply manual updates to the tag. Next, bind the click actions of the tag to the methods of the ZoomViewModel. It is also possible to bind the tag's conditional CSS classes to the ZoomViewModel's properties when determining the current min/max zoom level.

<script type="riot/tag">

    <!-- tag template -->

    <div class="zoom-btns">
      <div class="{ button: true, circle: true, raised: true, disable: !opts.zoomVM.canZoomIn }"
        onclick="{ zoomIn }">
        <i class="material-icons">add</i>
      <div class="{ button: true, circle: true, raised: true, disable: !opts.zoomVM.canZoomOut }"
        onclick="{ zoomOut }">
        <i class="material-icons">remove</i>
    <div class="view-info">Scale: { opts.view.scale.toFixed(1) }</div>
    <div class="view-info">Zoom: { opts.view.zoom.toFixed(2) }</div>

    // tag logic

    // optional: set the UI position of the tag within the view
    if (this.opts.view_ui_position) {
      this.opts.view.ui.add(this.root, this.opts.view_ui_position);

    // watch view properties for changes and then manually update the tag
    // to update its scale and zoom expressions on the page'scale,zoom', function() {

    // event handler for a div onclick in the tag template
    zoomIn() {
      if (this.opts.zoomVM.canZoomIn) {

    // event handler for a div onclick in the tag template
    zoomOut() {
      if (this.opts.zoomVM.canZoomOut) {


4. Render the custom Riot tag

Add your custom tag to the DOM. You can also specify a view UI layout position for the tag. Finally, "mount" it to the page with Riot, passing in the view instance and a ZoomViewModel.

<div id="viewDiv">
  <zoom-buttons view_ui_position="bottom-left"></zoom-buttons>
view.when(function(view) {
  // using riot.js:
  //  - mount the custom zoom buttons tag onto the page
  //  - pass in properties to the tag (i.e. the MapView and a ZoomViewModel)
  riot.mount("zoom-buttons", {
    view: view,
    zoomVM: new ZoomVM({
      view: view

Sample search results