Hello.
Making an app with widgets like search and basemapToggle in API 4x.
All my widgets are being minimized by using the "Exapand" widget, my problem is that i need to close a widget before I open another one, otherwise both widgets stay open and overlap each other (as seen on attached png):
So instead of this happening I would actually want one widget to close automatically when I open another one, in this case the search widget to automatically close when I open the basemapToggle one (and wise versa)
Does anyone have some good solutions for me regarding this?
Solved! Go to Solution.
And here is a sample for what Rene is talking about:
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">
<title>Expand widget [beta] - 4.5</title>
<link rel="stylesheet" href="https://js.arcgis.com/4.5/esri/css/main.css">
<script src="https://js.arcgis.com/4.5/"></script>
<style>
html,
body,
#viewDiv {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
</style>
<script>
var bgExpand, bgExpand2, expandHandle1, expandHandle2;
require([
"esri/Map",
"esri/views/SceneView",
"esri/widgets/Expand",
"esri/widgets/BasemapGallery",
"esri/widgets/Search",
"esri/core/watchUtils",
"dojo/domReady!"
], function(
Map, SceneView, Expand, BasemapGallery, Search, watchUtils
) {
var map = new Map({
basemap: "satellite"
});
var view = new SceneView({
container: "viewDiv",
map: map
});
// Create a BasemapGallery widget instance and set
// its container to a div element
var basemapGallery = new BasemapGallery({
view: view,
container: document.createElement("div")
});
var searchWidget = new Search({
view: view,
container: document.createElement("div")
});
// Create an Expand instance and set the content
// property to the DOM node of the basemap gallery widget
// Use an Esri icon font to represent the content inside
// of the Expand widget
bgExpand = new Expand({
view: view,
content: basemapGallery.container,
expandIconClass: "esri-icon-basemap"
});
bgExpand2 = new Expand({
view: view,
content: searchWidget.container,
expandIconClass: "esri-icon-search"
});
expandHandle1 = watchUtils.pausable(bgExpand, "expanded", function(newValue, oldValue){
if(newValue === true){
expandHandle1.pause();
setTimeout(function(){
expandHandle2.resume();
}, 100);
}else{
expandHandle1.resume();
}
if(bgExpand2.expanded){
bgExpand2.collapse();
}
});
expandHandle2 = watchUtils.pausable(bgExpand2, "expanded", function(newValue, oldValue){
if(newValue === true){
expandHandle2.pause();
setTimeout(function(){
expandHandle1.resume();
}, 100);
}else{
expandHandle2.resume();
}
if(bgExpand.expanded){
bgExpand.collapse();
}
});
// Add the expand instance to the ui
view.ui.add(bgExpand, "top-right");
view.ui.add(bgExpand2, "top-right");
});
</script>
</head>
<body>
<div id="viewDiv"></div>
</body>
</html>
You could watch for the "expanded" property of each one, when one changes, change all the others.
This functionality is going to be coming to 4.6, which is coming soon!
And here is a sample for what Rene is talking about:
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">
<title>Expand widget [beta] - 4.5</title>
<link rel="stylesheet" href="https://js.arcgis.com/4.5/esri/css/main.css">
<script src="https://js.arcgis.com/4.5/"></script>
<style>
html,
body,
#viewDiv {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
</style>
<script>
var bgExpand, bgExpand2, expandHandle1, expandHandle2;
require([
"esri/Map",
"esri/views/SceneView",
"esri/widgets/Expand",
"esri/widgets/BasemapGallery",
"esri/widgets/Search",
"esri/core/watchUtils",
"dojo/domReady!"
], function(
Map, SceneView, Expand, BasemapGallery, Search, watchUtils
) {
var map = new Map({
basemap: "satellite"
});
var view = new SceneView({
container: "viewDiv",
map: map
});
// Create a BasemapGallery widget instance and set
// its container to a div element
var basemapGallery = new BasemapGallery({
view: view,
container: document.createElement("div")
});
var searchWidget = new Search({
view: view,
container: document.createElement("div")
});
// Create an Expand instance and set the content
// property to the DOM node of the basemap gallery widget
// Use an Esri icon font to represent the content inside
// of the Expand widget
bgExpand = new Expand({
view: view,
content: basemapGallery.container,
expandIconClass: "esri-icon-basemap"
});
bgExpand2 = new Expand({
view: view,
content: searchWidget.container,
expandIconClass: "esri-icon-search"
});
expandHandle1 = watchUtils.pausable(bgExpand, "expanded", function(newValue, oldValue){
if(newValue === true){
expandHandle1.pause();
setTimeout(function(){
expandHandle2.resume();
}, 100);
}else{
expandHandle1.resume();
}
if(bgExpand2.expanded){
bgExpand2.collapse();
}
});
expandHandle2 = watchUtils.pausable(bgExpand2, "expanded", function(newValue, oldValue){
if(newValue === true){
expandHandle2.pause();
setTimeout(function(){
expandHandle1.resume();
}, 100);
}else{
expandHandle2.resume();
}
if(bgExpand.expanded){
bgExpand.collapse();
}
});
// Add the expand instance to the ui
view.ui.add(bgExpand, "top-right");
view.ui.add(bgExpand2, "top-right");
});
</script>
</head>
<body>
<div id="viewDiv"></div>
</body>
</html>
Hey and thanks for the answers, have made the altercations but the problem still persists, could you take a look at my setup?
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
<title>Hlynur experiments</title>
<style>
html,
body,
#viewDiv {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
#layerToggle1 {
top: 13px;
right: 13px;
width: 165px;
position: absolute;
float: right;
color: #86888A;
text-align: left;
font-family: "arial";
font-size: 14px;
padding: 5px 2px;
background-color: white;
outline-color: white;
box-shadow: 1px 1px #bdbdbd;
}
#layerToggle2 {
top: 37px;
right: 13px;
width: 165px;
position: absolute;
float: right;
color: #86888A;
text-align: left;
font-family: "arial";
font-size: 14px;
padding: 5px 2px;
background-color: white;
outline-color: white;
box-shadow: 1px 1px #bdbdbd;
}
</style>
<link rel="stylesheet" href="https://js.arcgis.com/4.5/esri/css/main.css">
<script src="https://js.arcgis.com/4.5/"></script>
<script>
require([
"esri/Map",
"esri/views/MapView",
"esri/widgets/Home",
"esri/widgets/Zoom",
"esri/widgets/BasemapToggle",
"esri/tasks/Locator",
"esri/widgets/Search",
"esri/widgets/Expand",
"esri/layers/FeatureLayer",
"esri/core/watchUtils",
"dojo/dom",
"dojo/on",
"dojo/domReady!"
], function(
Map,
MapView,
Home,
Zoom,
BasemapToggle,
Locator,
Search,
Expand,
FeatureLayer,
watchUtils,
dom,
on,
) {
var map = new Map({
basemap: "gray",
});
var view = new MapView({
container: "viewDiv",
map: map,
zoom: 9,
extent: {
xmin: -3730050,
ymin: 6277314,
xmax: 4468890,
ymax: 12147678,
spatialReference: 102100
}
});
var homeWidget = new Home({
view: view
});
var basemapToggle = new BasemapToggle({
view: view,
nextBasemap: "satellite",
container: document.createElement("div")
});
var basemapToggleExpand = new Expand({
view: view,
content: basemapToggle.container,
expandIconClass: "esri-icon-basemap",
});
var searchWidget = new Search({
view:view,
allPlaceholder: "Incident or address",
container: document.createElement("div"),
sources: [
{
locator: new Locator({ url: "//geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer" }),
singleLineFieldName: "SingleLine",
name: "Adress search",
localSearchOptions: {
minScale: 300000,
distance: 50000
},
maxResults: 3,
maxSuggestions: 6,
suggestionsEnabled: false,
minSuggestCharacters: 0,
resultGraphicEnabled: false
},{
featureLayer: new FeatureLayer({
url: "https://services1.arcgis.com/LpQVI6wAjYbHDKAK/arcgis/rest/services/Report_Service/FeatureServer/0",
popupTemplate: {
title: "{Incident_Type} </br> {Incident_Description}",
overwriteActions: true
}
}),
searchFields: ["Incident_Type"],
displayField: "Incident_Description",
exactMatch: false,
outFields: ["Incident_Type", "Report_Date"],
name: "Incident",
placeholder: "huh?",
zoomScale: 10000,
resultGraphicEnabled: false
}, {
featureLayer: new FeatureLayer({
url: "https://services1.arcgis.com/LpQVI6wAjYbHDKAK/arcgis/rest/services/Iceland_Test/FeatureServer/0",
popupTemplate: {
title: "{Name}",
overwriteActions: true
}
}),
searchFields: ["Name"],
suggestionTemplate: "{Name}",
exactMatch: false,
outFields: ["Name"],
name: "Basecamps",
zoomScale: 5000,
resultGraphicEnabled: false
}],
popupEnabled: false
});
var searchWidgetExpand = new Expand({
view: view,
content: searchWidget.container,
expandIconClass: "esri-icon-search",
});
var reportLyr = new FeatureLayer({
url: "https://services1.arcgis.com/LpQVI6wAjYbHDKAK/arcgis/rest/services/Report_Service/FeatureServer/0",
id: "report",
visible: false,
popupTemplate: {
title: "{Incident_Type}",
content: [{
type: "text",
text: "Here something seriously interresting has taken place, stay tuned for more AMAZING adventures!!!"
}]
},
outFields: ["*"]
});
var reportLyrToggle = dom.byId("reportLyr");
on(reportLyrToggle, "change", function() {
reportLyr.visible = reportLyrToggle.checked;
});
var icelandLyr = new FeatureLayer({
url: "https://services1.arcgis.com/LpQVI6wAjYbHDKAK/arcgis/rest/services/Iceland_Test/FeatureServer/0",
id: "iceland",
visible: false,
popupTemplate: {
title: "Basecamp",
content: [{
type: "text",
Text: "Place: {Name} <br/> Region: {Region}"
}, {
type: "media",
mediaInfos: [{
title: "{Name}",
type: "image",
value: {
sourceURL: "{PICTURE}"
}
}]
}, {
type: "attachments"
}],
actions: [{
id: "see-more",
className: "esri-icon-home",
title: "Visit homepage"
}]
},
outFields: ["*"]
});
var icelandLyrToggle = dom.byId("icelandLyr");
on(icelandLyrToggle, "change", function() {
icelandLyr.visible = icelandLyrToggle.checked;
});
expandhandle1 = watchUtils.pausable(basemapToggleExpand, "expanded", function(newValue, oldValue){
if(newValue === true){
expandHandle1.pause();
setTimeout(function(){
expandHandle2.resume();
}, 100);
}else{
expandHandle1.resume();
}
if(searchWidgetExpand.expanded){
searchWidgetExpand.collapse();
}
});
expandhandle2 = watchUtils.pausable(searchWidgetExpand, "expanded", function(newValue, oldValue){
if(newValue === true){
expandHandle2.pause();
setTimeout(function(){
expandHandle1.resume();
}, 100);
}else{
expandHandle2.resume();
}
if(basemapToggleExpand.expanded){
basemapToggleExpand.collapse();
}
});
view.on("layerview-create", function(event) {if (event.layer.id === "report") {console.log("LayerView for reports created!", event.layerView)};
});
view.on("layerview-create", function(event) {if (event.layer.id === "iceland") {console.log("Layerview for Iceland created!", event.layerView)}
});
map.add(reportLyr);
map.add(icelandLyr);
view.ui.add(homeWidget, {position: "top-left", index: 1});
view.ui.add(searchWidgetExpand, {position: "top-left", index: 3});
view.ui.add(basemapToggleExpand, {position: "top-left", index: 2});
view.then(function () {
var popup = view.popup;
popup.viewModel.on("trigger-action", function(event) {
if (event.action.id === "see-more") {
var attributes = popup.viewModel.selectedFeature.attributes;
var info = attributes.Link;
if (info !== null) {
window.open(info.trim());
} else {
window.open ("https://www.google.com/search?q=" +
attributes.Name);
}
}
});
});
});
</script>
</head>
<body>
<div id="viewDiv"></div>
<span id="layerToggle1">
<input type="checkbox" id="reportLyr">Hlynur has issues
</span>
<span id="layerToggle2">
<input type="checkbox" id="icelandLyr">Hlynur has basecamps
</span>
</body>
</html>
Hlynur,
JS is a case sensitive language and you had expandhandle1 instead of expandHandle1:
expandHandle1 = watchUtils.pausable(basemapToggleExpand, "expanded", function(newValue, oldValue) {
if (newValue === true) {
expandHandle1.pause();
setTimeout(function() {
expandHandle2.resume();
}, 100);
} else {
expandHandle1.resume();
}
if (searchWidgetExpand.expanded) {
searchWidgetExpand.collapse();
}
});
expandHandle2 = watchUtils.pausable(searchWidgetExpand, "expanded", function(newValue, oldValue) {
if (newValue === true) {
expandHandle2.pause();
setTimeout(function() {
expandHandle1.resume();
}, 100);
} else {
expandHandle2.resume();
}
if (basemapToggleExpand.expanded) {
basemapToggleExpand.collapse();
}
});
Excellent, works like a dream! Thanks so much for the quick assistance.
One more thing as I have you on the line, in my searchWidget, do I have to reference the featureLayers being search as new FeatureLayer or can I somehow just reference their "id's" as they are also being added to the map itself?
What is the purpose of the timer in your solution? Why not just check the newValue and expanded property?
To handle a race issue.
This thread should solve your problem. https://community.esri.com/thread/201369-wab-how-do-i-edit-the-group-widget-layout
Thomas,
This thread is not about WAB it is a JS API 4.x question.