IDEA
|
Post is almost 5 years old. I believe ESRI has partially added this functionality. I know certain versions of Enterprise allow you to update the service url for feature services. Updating the URL for map services requires a slightly different approach. You can remove and re-add the layers but then you run into a bunch of updates at the app level. We've adopted the approach of copying the web map json config locally and just updating the map service URLs in those files. Still requires manual updates but the map ID is maintained with that approach.
... View more
08-14-2023
05:53 AM
|
0
|
0
|
236
|
POST
|
Hi Cameron - I don't think ESRI has any plans to add this as an enhancement. WAB/3.X will be retired in the next year. You can add the "reorderPopupFeatures" and "sortFeatures" functions shown below to the PopupManager.js file that is bundled with the web appbuilder source code. Make sure to add "this.reorderPopupFeatures();" at the end of the init function. The example below (also attached) is the entire PopupManager.js file that gets bundled with WAB. It's from version 2.19. FYI - I believe ESRI runs an identify operation by service to get the popup features when the user clicks on the map. All of those identify requests are done asynchronously and there is no guarantee what order they come back in. ESRI could run all of that synchronously but that could create lag/bottlenecks. The example presented in this response simply sorts the features array by layer order. ///////////////////////////////////////////////////////////////////////////
// Copyright © 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',
'dojo/_base/lang',
'dojo/_base/html',
'dojo/topic',
'dojo/on',
'dojo/query',
'./FeatureActionManager',
'./utils',
'./dijit/FeatureActionPopupMenu',
'./RelatedRecordsPopupProjector',
'dojo/_base/array',
'dojo/promise/all',
'dojo/Deferred',
'dojo/aspect',
'./LayerStructure'], function(declare, lang, html, topic, on, query, FeatureActionManager,
jimuUtils, PopupMenu, RelatedRecordsPopupProjector,array, all, Deferred, aspect, LayerStructure) {
var instance = null;
var clazz = declare(null, {
mapManager: null,
// popupUnion = {
// mobile: is mobile popup of map,
// bigScreen: is popup of map
// };
popupUnion: null,
_relatedRecordsPopupProjector: null,
constructor: function(options) {
lang.mixin(this, options);
this.popupMenu = PopupMenu.getInstance();
this.isInited = false;
this.featureActionManager = FeatureActionManager.getInstance();
topic.subscribe("mapLoaded", lang.hitch(this, this.onMapLoadedOrChanged));
topic.subscribe("mapChanged", lang.hitch(this, this.onMapLoadedOrChanged));
topic.subscribe("appConfigChanged", lang.hitch(this, this._onAppConfigChanged));
topic.subscribe("widgetsActionsRegistered", lang.hitch(this, this._onWidgetsActionsRegistered));
},
init: function() {
this.popupUnion = this.mapManager.getMapInfoWindow();
if(!this.popupUnion.bigScreen || !this.popupUnion.mobile ||
!this.popupUnion.bigScreen.domNode || !this.popupUnion.mobile.domNode){
return;
}
if(!this.isInited){
this._createPopupMenuButton();
this._bindSelectionChangeEvent();
this.isInited = true;
}
this.reorderPopupFeatures();
},
reorderPopupFeatures: function() {
var that = this;
this.layerStructrue = LayerStructure.getInstance();
// intercept the popup.setFeatures method, reorder feautres and recall original popup.setFeatures method.
aspect.around(this.popupUnion.bigScreen, "setFeatures", function(originalSetFeatures) {
return function(featuresArg, options) {
var convertedFeatureDefs = [];
// having to consider that there are two categories of features parameter can be received.
// 1, feature array
// 2, deferred array
array.forEach(featuresArg, function(featureOrDef) {
if(featureOrDef.declaredClass === "esri.Graphic") {
// it is a feature
var def = new Deferred();
def.resolve([featureOrDef]);
convertedFeatureDefs.push(def);
} else {
// it is a deferred
convertedFeatureDefs.push(featureOrDef);
}
});
this.clearFeatures();
all(convertedFeatureDefs).then(lang.hitch(this, function(results) {
var features = [];
array.forEach(results, function(result) {
array.forEach(result, function(feature) {
if(feature) {
// remove duplicated features
var featureAlreadyExist = array.some(features, function(f) {
if(feature === f) {
return true;
} else {
return false;
}
});
if(!featureAlreadyExist) {
features.push(feature);
}
}
});
}, this);
// sort features by layers order.
var orderedFeatures = that.sortFeatures(features);
// recall origin setFeatures.
originalSetFeatures.apply(this, [orderedFeatures, options]);
}));
};
});
// js-api will using options.closetFirst paramether to show popup by default when clicking the map.
// this paramether will impact features order, so having to deny it.
// that means the closeFirst parameter will never tack effect for show popup in the WAB environment.
aspect.around(this.popupUnion.bigScreen, 'show', function(originalShow) {
return function(location/*, options*/) {
originalShow.apply(this, [location, false]);
};
});
aspect.around(this.popupUnion.mobile, 'show', function(originalShow) {
return function(location/*, options*/) {
originalShow.apply(this, [location, false]);
};
});
},
// accordiing to layers order to sort features
sortFeatures: function(features) {
if(!this.layerOrderPriority) {
// according to layers order to define a priority object, using to sort features.
this.layerOrderPriority = {};
var priority = 1;
this.layerStructrue.traversal(lang.hitch(this, function(layerNode) {
this.layerOrderPriority[layerNode.id] = priority++;
}));
}
// update this.layerOrderPriority if the layer structure has been changed.
if(!this.layerStructureChangeHandler) {
this.layerStructureChangeHandler = this.layerStructrue.on('structure-change', lang.hitch(this, function() {
this.layerOrderPriority = null;
}));
}
array.forEach(features, function(feature) {
if(feature && feature.getLayer) {
feature._priority = this.layerOrderPriority[feature.getLayer().id];
} else {
feature._priority = 100000;
}
}, this);
// features.sort(function(featureA, featureB) {
// return featureA._priority > featureB._priority;
// });
features.sort(function(featureA, featureB) {
if(featureA._priority > featureB._priority)
{ return 1;}
else
{ return -1;}
return 0;
});
return features;
},
_createPopupMenuButton: function(){
if(this.popupMenuButtonDesktop) {
html.destroy(this.popupMenuButtonDesktop);
}
if(this.popupMenuButtonMobile) {
html.destroy(this.popupMenuButtonMobile);
}
this.popupMenuButtonDesktop = html.create('span', {
'class': 'popup-menu-button'
}, query(".actionList", this.popupUnion.bigScreen.domNode)[0]);
var mobileActionListNode =
query("div.esriMobileInfoView.esriMobilePopupInfoView .esriMobileInfoViewItem").parent()[0];
var mobileViewItem = html.create('div', {
'class': 'esriMobileInfoViewItem'
}, mobileActionListNode);
this.popupMenuButtonMobile = html.create('span', {
'class': 'popup-menu-button'
}, mobileViewItem);
on(this.popupMenuButtonMobile, 'click', lang.hitch(this, this._onPopupMenuButtonClick));
on(this.popupMenuButtonDesktop, 'click', lang.hitch(this, this._onPopupMenuButtonClick));
},
_onPopupMenuButtonClick: function(evt){
var position = html.position(evt.target);
if(this.menuActionsOfSelectedFeature) {
this.popupMenu.setActions(this.menuActionsOfSelectedFeature);
}
this.popupMenu.show(position);
},
_bindSelectionChangeEvent: function(){
on(this.popupUnion.bigScreen, "show,selection-change", lang.hitch(this, this._onSelectionChange));
on(this.popupUnion.mobile, "show,selection-change", lang.hitch(this, this._onSelectionChange));
},
_onSelectionChange: function(evt){
this.selectedFeature = evt.target.getSelectedFeature();
//this.selectedFeature = this.mapManager.map.infoWindow.getSelectedFeature();
if(!this.selectedFeature){
this._disablePopupMenu();
return;
}
node = dojo.query("[dojoattachpoint=\"_title\"]", this.popupUnion.bigScreen.domNode)[0];
node2 = dojo.query("[dojoattachpoint=\"_description\"]", this.popupUnion.bigScreen.domNode)[0];
this.initPopupMenu([this.selectedFeature]);
var selectedFeatureLayer = this.selectedFeature.getLayer();
var hasInfoTemplate = this.selectedFeature.infoTemplate ||
(selectedFeatureLayer && selectedFeatureLayer.infoTemplate);
if(hasInfoTemplate) {
//this._createRelatedRecordsPopupProjector(this.selectedFeature);
}
},
_disablePopupMenu: function() {
html.addClass(this.popupMenuButtonDesktop, 'disabled');
html.addClass(this.popupMenuButtonMobile, 'disabled');
},
_enablePopupMenu: function() {
html.removeClass(this.popupMenuButtonDesktop, 'disabled');
html.removeClass(this.popupMenuButtonMobile, 'disabled');
},
// public method, can be called from outside.
initPopupMenu: function(features){
if(!features) {
this._disablePopupMenu();
this.popupMenu.setActions([]);
return;
}
var featureSet = jimuUtils.toFeatureSet(features);
this.featureActionManager.getSupportedActions(featureSet).then(lang.hitch(this, function(actions){
var excludeActions = ['ZoomTo', 'ShowPopup', 'Flash', 'ExportToCSV',
'ExportToFeatureCollection', 'ExportToGeoJSON', 'ShowRelatedRecords',
'SaveToMyContent', 'CreateLayer'];
var popupActions = actions.filter(lang.hitch(this, function(action){
return excludeActions.indexOf(action.name) < 0 ;
}));
if(popupActions.length === 0){
this._disablePopupMenu();
}else{
this._enablePopupMenu();
}
var menuActions = popupActions.map(lang.hitch(this, function(action){
//action.data = jimuUtils.toFeatureSet(feature);
action.data = featureSet;
return action;
}));
this.menuActionsOfSelectedFeature = menuActions;
this.popupMenu.setActions(menuActions);
}));
},
/******************************
* Events
******************************/
onMapLoadedOrChanged: function() {
this.isInited = false;
this.init();
},
_onAppConfigChanged: function() {
if(this.popupUnion) {
if(this.popupUnion.bigScreen && this.popupUnion.bigScreen.hide) {
this.popupUnion.bigScreen.hide();
this.popupMenu.hide();
}
if(this.popupUnion.mobile && this.popupUnion.mobile.hide) {
this.popupUnion.mobile.hide();
this.popupMenu.hide();
}
}
},
_onWidgetsActionsRegistered: function(){
//to init actions
this.init();
},
/**********************************
* Methods for show related records
**********************************/
_createRelatedRecordsPopupProjector: function(selectedFeature) {
try {
if(this._relatedRecordsPopupProjector &&
this._relatedRecordsPopupProjector.domNode) {
this._relatedRecordsPopupProjector.destroy();
this._relatedRecordsPopupProjector = null;
}
//var refDomNode = query(".esriViewPopup", this.popupUnion.bigScreen.domNode)[0];
this._relatedRecordsPopupProjector = new RelatedRecordsPopupProjector({
originalFeature: selectedFeature,
//refDomNode: refDomNode,
popup: this.mapManager.map.infoWindow,
popupManager: this
});
} catch(err) {
console.warn(err.message);
}
}
});
clazz.getInstance = function(mapManager) {
if (instance === null) {
instance = new clazz({
mapManager: mapManager
});
}
return instance;
};
return clazz;
});
... View more
08-09-2023
12:10 PM
|
0
|
0
|
1131
|
POST
|
I'm upgrading my WAB apps from 2.19 to 2.25 and I've noticed that customizations to CSS classes are not maintained and the upgrade drops changes I've made to the PopupManager.js file. Additionally, settings defined in our web.config file are not copied over. Is this normal behavior in the upgrade process or should those changes be maintained during the upgrade? I upgraded all apps at once. I may try to upgrade the apps one at a time but I expect the behavior to be the same.
... View more
09-08-2022
08:41 AM
|
0
|
0
|
301
|
POST
|
Here is a link to a similar thread that describes the state issue and presents two ways to resolve the synchronization error. https://community.esri.com/t5/arcgis-experience-builder-questions/widgets-not-synchronized-when-added-to-multiple/m-p/1190113#M4814
... View more
07-07-2022
09:51 AM
|
0
|
0
|
1864
|
POST
|
Grant, Thank you very much for the helpful feedback. I was able to resolve the issue by using global variables stored in the window. It's not the most ideal solution and I will investigate the state manager in the redux store, but the global var approach is sufficient for our simple use case. Thank you again.
... View more
07-07-2022
09:50 AM
|
0
|
0
|
656
|
POST
|
I can reuse the widgets by adding them into the pending tab but the widgets get destroyed and recreated whenever the layout changes. This is not ideal since users may toggle something on and then resize the window but the widget will show the layer as being off. I imagine there must be a way to maintain the widget state between layouts.
... View more
07-07-2022
08:37 AM
|
0
|
1
|
1865
|
POST
|
I've developed an app in ArcGIS Experience Builder using the developer edition 1.8. I configured a custom layer list widget and added it to the custom layouts I defined for medium and small screen devices. I run into an issue with the default layer settings in the input checkboxes being restored when the app is resized. For example, I toggle a layer off and then resize the map to small screen and the toggle button is turned back on. The layer in the map is correctly turned off but the input checkboxes get restored to the default configuration every time the layout is switched. Is there anyway to keep the custom layer list widgets synchronized in each layout or is it possible to use the widget only once and have it display in the custom layouts? I'm able to get it working using the AUTO layout option for medium and small screen devices but that causes display issues.
... View more
07-06-2022
01:54 PM
|
0
|
2
|
739
|
POST
|
I've ran into a similar issue with designing an app for mobile responsiveness. I have enabled a custom layout to be used on medium and small screen sizes but my custom layer list widget only displays on the full screen default layout. I thought there was an easy solution that involved make duplicates of the widget for the other layouts but that causes synchronization issues when layers get toggled on and off. Is there a way to reuse the same widget in the other layouts or must I create duplicates?
... View more
07-06-2022
11:45 AM
|
0
|
3
|
1871
|
IDEA
|
My organization is transitioning to Experience Builder and we would like to see a theme similar to the Plateau theme offered in WAB. Most of our WAB content was developed using the foldable and tab themes but we have a few use cases where Plateau is required.
... View more
06-28-2022
06:45 AM
|
1
|
0
|
512
|
POST
|
Tonghui, Thanks for the helpful info. I've actually developed a custom group filter widget that works like WAB's " but with a simplified UI. We are trying to mimic WAB's Plateau theme with a search bar, layer list and filter up in the panel on the right-hand side of the app. We were able to get a similar UI in Experience Builder but we had to use a sidebar on the right with a layer list, search bar up on the top right and filter off on the left with the general map controls. The alignment issue we were having was when we tried to dock the filter icon up in the fixed panel on the right with the search tool. The attached image illustrates the issue. Notice how the widget controller overlaps with the search tool in order to get the filter icon to display.
... View more
06-28-2022
06:36 AM
|
0
|
0
|
1231
|
POST
|
Hello, I am new to Experience Builder and I am having trouble getting a widget icon aligned properly in the widget controller. The widget controller consists of a single filter widget. The icon for the filter widget is aligned in the center of the controller but it does not display when the controller is resized below 100px. Is there anyway to get the icon aligned on the left of the controller? Using Experience Builder Developer Edition 1.8. Including two pics that illustrate the issue.
... View more
06-27-2022
12:15 PM
|
0
|
2
|
1252
|
POST
|
This is possible using the developer edition. Follow the steps below. FYI - I got the below snippets off a similar thread a few years back but I can't seem to find the link. The code below will work for WAB but you probably should consider moving to Experience Builder/4.X. I'm not sure how much additional support the 3.X builder will be getting before it is retired. (1) Open the popupmanager.js file (2) Add "this.reorderPopupFeatures();" at the end of the init method (3) Add the two methods listed below to the popupmanager.js file. reorderPopupFeatures: function() { var that = this; this.layerStructrue = LayerStructure.getInstance(); aspect.around(this.popupUnion.bigScreen, "setFeatures", function(originalSetFeatures) { return function(featuresArg, options) { var convertedFeatureDefs = []; array.forEach(featuresArg, function(featureOrDef) { if(featureOrDef.declaredClass === "esri.Graphic") { var def = new Deferred(); def.resolve([featureOrDef]); convertedFeatureDefs.push(def); } else { convertedFeatureDefs.push(featureOrDef); } }); this.clearFeatures(); all(convertedFeatureDefs).then(lang.hitch(this, function(results) { var features = []; array.forEach(results, function(result) { array.forEach(result, function(feature) { if(feature) { var featureAlreadyExist = array.some(features, function(f) { if(feature === f) { return true; } else { return false; } }); if(!featureAlreadyExist) { features.push(feature); } } }); }, this); var orderedFeatures = that.sortFeatures(features); originalSetFeatures.apply(this, [orderedFeatures, options]); })); }; }); aspect.around(this.popupUnion.bigScreen, 'show', function(originalShow) { return function(location/*, options*/) { originalShow.apply(this, [location, false]); }; }); aspect.around(this.popupUnion.mobile, 'show', function(originalShow) { return function(location/*, options*/) { originalShow.apply(this, [location, false]); }; }); }, sortFeatures: function(features) { if(!this.layerOrderPriority) { this.layerOrderPriority = {}; var priority = 1; this.layerStructrue.traversal(lang.hitch(this, function(layerNode) { this.layerOrderPriority[layerNode.id] = priority++; })); } if(!this.layerStructureChangeHandler) { this.layerStructureChangeHandler = this.layerStructrue.on('structure-change', lang.hitch(this, function() { this.layerOrderPriority = null; })); } array.forEach(features, function(feature) { if(feature && feature.getLayer) { feature._priority = this.layerOrderPriority[feature.getLayer().id]; } else { feature._priority = 100000; } }, this); features.sort(function(featureA, featureB) { if(featureA._priority > featureB._priority) { return 1;} else { return -1;} return 0; }); return features; },
... View more
06-07-2022
11:44 AM
|
1
|
0
|
1888
|
POST
|
I've created a python toolbox in ArcGIS Pro 2.8 and I published the toolbox as a geoprocessing service on our hosting server. One of the parameters I have defined is for a GPFeatureLayer (see below). I'm able to select the layer in ArcGIS Pro but I get prompted to add the json representation of the layer from ArcGIS Server. I'd like to reference the feature layer by service URL preferably or by an sde connection as a fallback. Is there anyway to pass a service url as the value for the input? param3 = arcpy.Parameter( displayName="FeatureLayer", name="FeatureLayer", datatype="GPFeatureLayer", parameterType="Required", direction="Input")
... View more
07-26-2021
12:52 PM
|
0
|
0
|
745
|
POST
|
thread - https://community.esri.com/t5/arcgis-web-appbuilder-questions/web-app-not-working-on-chrome/td-p/1040380
... View more
03-30-2021
08:06 AM
|
0
|
2
|
3581
|
POST
|
I would contact esri tech support over chat and request a case if you have a maintenance agreement with them. Our organization pushed chrome updates about a week ago and another esri thread mentions they think there is an issue with the chrome profiles. Our issue had me very puzzled as the same source code worked from our internal domain but not from our public facing box.
... View more
03-29-2021
11:26 AM
|
2
|
4
|
3652
|
Title | Kudos | Posted |
---|---|---|
1 | 06-07-2022 11:44 AM | |
1 | 03-11-2021 12:25 PM | |
1 | 06-28-2022 06:45 AM | |
1 | 03-26-2021 06:57 AM | |
1 | 03-26-2021 11:55 AM |
Online Status |
Offline
|
Date Last Visited |
03-27-2024
06:51 AM
|