Save a web scene

Explore in the sandboxView live

This sample demonstrates how to save a WebScene to a Portal for ArcGIS item by either creating a new item or overwriting an existing item that has been loaded from a Portal for ArcGIS item.

Saving a web scene is easy. All that's required is a WebScene and a valid Portal to save the scene to.

Saving to a new item

Create a new empty WebScene instance and a Portal instance where the WebScene should be saved to. Loading the Portal will trigger user authentication, and if successful the item will be saved to the given Portal.

Load a basic webscene
                                                                                                                                                                       
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
    <title>Save a web scene | Sample | ArcGIS API for JavaScript 4.20</title>

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

    <style>
      html,
      body,
      #viewDiv {
        padding: 0;
        margin: 0;
        height: 100%;
        width: 100%;
      #sidebarDiv {
        width: 240px;
        padding: 10px;
        height: 200px;
      #overlayDiv {
        z-index: 1;
        position: absolute;
        margin: auto auto;
        top: 0;
        right: 0;
        bottom: 0;
        left: 0;
        width: 280px;
        height: 180px;
        padding: 10px;
        background-color: white;
        border: 1px solid grey;
        visibility: hidden;
      input[type="text"] {
        width: 100%;
    </style>

    <script>
      require([
        "esri/views/SceneView",
        "esri/WebScene",
        "esri/widgets/BasemapGallery",
        "esri/widgets/Expand"
      ], (SceneView, WebScene, BasemapGallery, Expand) => {
        /************************************************************
         * Creates a new WebScene instance. A WebScene can reference
         * a PortalItem ID that represents a WebScene saved to
         * arcgis.com or an on-premise portal.
         *
         * To load a WebScene from an on-premise portal, set the portal
         * url with esriConfig.portalUrl (see above).
         ************************************************************/
        const scene = new WebScene({
          portalItem: {
            // autocasts as new PortalItem()
            id: "90e3c30bdbbe4886a94f75c2cdd7edce"
          }
        });

        /************************************************************
         * Set the WebScene instance to the map property in a
         * SceneView.
         ************************************************************/
        const view = new SceneView({
          map: scene,
          container: "viewDiv"
        });
        // add basemapGallery widgets
            new Expand({
              content: new BasemapGallery({
                view: view
              view: view
          "top-left"
        view.when(() => {
          // When the webscene and view resolve, display the webscene's
          // new title in the Div
          const title = document.getElementById("webSceneTitle");
          const save = document.getElementById("saveWebScene");
          save.disabled = false;
          save.addEventListener("click", () => {
            document.getElementById("saveWebScene").disabled = true;
            document.getElementById("saveWebScene").classList.add("esri-button--secondary");
            // item automatically casts to a PortalItem instance by saveAs
            const item = {
              title: title.value
            // Update properties of the WebScene related to the view.
            // This should be called just before saving a webscene.
            scene.updateFrom(view).then(() => {
                // Saved successfully
                .then((item) => {
                  // link to the newly-created web scene item
                  const itemPageUrl = item.portal.url + "/home/item.html?id=" + item.id;
                  const link = '<a target="_blank" href="' + itemPageUrl + '">' + title.value + "</a>";
                  statusMessage("Save WebScene", "<br> Successfully saved as <i>" + link + "</i>");
                // Save didn't work correctly
                .catch((error) => {
                  statusMessage("Save WebScene", "<br> Error " + error);
          const overlay = document.getElementById("overlayDiv");
          const ok = overlay.getElementsByTagName("input")[0];
          function statusMessage(head, info) {
            document.getElementById("saveWebScene").classList.remove("esri-button--secondary");
            document.getElementById("saveWebScene").disabled = false;
            document.getElementById("head").innerHTML = head;
            document.getElementById("info").innerHTML = info;
            overlay.style.visibility = "visible";
          ok.addEventListener("click", () => {
            overlay.style.visibility = "hidden";
          view.ui.add("sidebarDiv", "top-right");
    </script>
  </head>

  <body>
    <div id="viewDiv"></div>
    <div id="sidebarDiv" class="esri-widget">
      <h4 class="esri-heading">Save WebScene</h4>
      <label class="esri-feature-form__label">Title</label>
      <input id="webSceneTitle" type="text" class="esri-input" value="WebScene Saving Sample" /><br /><br />
      <input id="saveWebScene" type="button" value="Save" disabled class="esri-button" />
    </div>
    <div id="overlayDiv" class="esri-widget">
      <h4 class="esri-heading" id="head"></h4>
      <label id="info"></label><br /><br />
      <input type="button" value="OK" class="esri-button" />
    </div>
  </body>
</html>

In case the scene is added to a view, the scene can only be saved once the view properties are updated on the scene:

Save a webscene
                                                                                                                                                                       
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
    <title>Save a web scene | Sample | ArcGIS API for JavaScript 4.20</title>

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

    <style>
      html,
      body,
      #viewDiv {
        padding: 0;
        margin: 0;
        height: 100%;
        width: 100%;
      #sidebarDiv {
        width: 240px;
        padding: 10px;
        height: 200px;
      #overlayDiv {
        z-index: 1;
        position: absolute;
        margin: auto auto;
        top: 0;
        right: 0;
        bottom: 0;
        left: 0;
        width: 280px;
        height: 180px;
        padding: 10px;
        background-color: white;
        border: 1px solid grey;
        visibility: hidden;
      input[type="text"] {
        width: 100%;
    </style>

    <script>
      require([
        "esri/views/SceneView",
        "esri/WebScene",
        "esri/widgets/BasemapGallery",
        "esri/widgets/Expand"
      ], (SceneView, WebScene, BasemapGallery, Expand) => {
        /************************************************************
         ************************************************************/
        const scene = new WebScene({
          portalItem: {
            // autocasts as new PortalItem()
            id: "90e3c30bdbbe4886a94f75c2cdd7edce"
        /************************************************************
         ************************************************************/
        const view = new SceneView({
          map: scene,
          container: "viewDiv"
        // add basemapGallery widgets
            new Expand({
              content: new BasemapGallery({
                view: view
              view: view
          "top-left"
        view.when(() => {
          // When the webscene and view resolve, display the webscene's
          // new title in the Div
          const title = document.getElementById("webSceneTitle");
          const save = document.getElementById("saveWebScene");
          save.disabled = false;
          save.addEventListener("click", () => {
            document.getElementById("saveWebScene").disabled = true;
            document.getElementById("saveWebScene").classList.add("esri-button--secondary");
            // item automatically casts to a PortalItem instance by saveAs
            const item = {
              title: title.value
            // Update properties of the WebScene related to the view.
            // This should be called just before saving a webscene.
            scene.updateFrom(view).then(() => {
              scene
                .saveAs(item)
                // Saved successfully
                .then((item) => {
                  // link to the newly-created web scene item
                  const itemPageUrl = item.portal.url + "/home/item.html?id=" + item.id;
                  const link = '<a target="_blank" href="' + itemPageUrl + '">' + title.value + "</a>";

                  statusMessage("Save WebScene", "<br> Successfully saved as <i>" + link + "</i>");
                })
                // Save didn't work correctly
                .catch((error) => {
                  statusMessage("Save WebScene", "<br> Error " + error);
                });
            });
          const overlay = document.getElementById("overlayDiv");
          const ok = overlay.getElementsByTagName("input")[0];
          function statusMessage(head, info) {
            document.getElementById("saveWebScene").classList.remove("esri-button--secondary");
            document.getElementById("saveWebScene").disabled = false;
            document.getElementById("head").innerHTML = head;
            document.getElementById("info").innerHTML = info;
            overlay.style.visibility = "visible";
          ok.addEventListener("click", () => {
            overlay.style.visibility = "hidden";
          view.ui.add("sidebarDiv", "top-right");
    </script>
  </head>

  <body>
    <div id="viewDiv"></div>
    <div id="sidebarDiv" class="esri-widget">
      <h4 class="esri-heading">Save WebScene</h4>
      <label class="esri-feature-form__label">Title</label>
      <input id="webSceneTitle" type="text" class="esri-input" value="WebScene Saving Sample" /><br /><br />
      <input id="saveWebScene" type="button" value="Save" disabled class="esri-button" />
    </div>
    <div id="overlayDiv" class="esri-widget">
      <h4 class="esri-heading" id="head"></h4>
      <label id="info"></label><br /><br />
      <input type="button" value="OK" class="esri-button" />
    </div>
  </body>
</html>

Overwriting an existing item

Create a new WebScene instance and set the portal item ID inside the portalItem property of the WebScene. Loading the Portal will trigger user authentication, and if successful the item will be saved to the given Portal.

                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/************************************************************
 * Creates a new WebScene instance. A WebScene can reference
 * a PortalItem ID that represents a WebScene saved to
 * arcgis.com or an on-premise portal.
 ************************************************************/
const scene = new WebScene({
  portalItem: {
    id: "3a9976baef9240ab8645ee25c7e9c096"
  }
});

/************************************************************
 * Create a new Portal instance and request immediate user
 * authentication.
 ************************************************************/
const portal = new Portal({
  authMode: "immediate"
});

/************************************************************
 * Loading of either the scene or the portal will trigger
 * authentication and once both Promises are resolved, the
 * Webscene will be saved thereby overwriting the previously
 * loaded PortalItem with any changes that have occurred.
 ************************************************************/
scene.load().then(() => {
  portal.load().then(() => {
    scene.portalItem.title = "Modified WebScene";
    scene.portalItem.portal = portal;
    scene.save();
  });
});

To use load or save items from an on-premise portal, set the URL of the portal in esriConfig.portalUrl.

Please refer to the ArcGIS Organization portals for information on how the ArcGIS API for JavaScript makes use of working with portal items.

Your browser is no longer supported. Please upgrade your browser for the best experience. See our browser deprecation post for more details.