I have just upgraded to v4.29 and am trying to incorporate the LayerList widget to the rest of my site. All my calcite 2.6.x components are reactive to scale, i.e. I can set the scale in the menu and all components will change. I would like to do the same with the LayerList widget, however, I do not see a way to control the scale attribute. Am I missing something? Should I use the VM instead? Any ideas or suggestions?
Thanks,
René
Solved! Go to Solution.
After some trial and error I came up with the following. It is not perfect as some of the labels in the widget may not be calcite elements, however, this in combination with some CSS tricks will work.
The following is a basic example for the measurement widget. For the layerlist I used the VM and constructed it using Calcite components. I needed to manipulate it more than the widget could offer.
import type MeasurementWidget from "@arcgis/core/widgets/Measurement";
const measurement = useRef<MeasurementWidget>();
useEffect(() => {
if (mapView) {
Promise.all([
import('@arcgis/core/widgets/Measurement')
]).then(result => {
const MeasurementWidget = result[0].default;
measurement.current = new MeasurementWidget({
view: mapView,
container: elementIDs.measurement_widgetDivID
});
measurement.current.when().then((_measurement: MeasurementWidget) => {
// The Measurement Widget mutates after state change, therefore we cannot use reactiveUtils.
const widgetDiv = document.getElementById(elementIDs.measurement_widgetDivID);
if (widgetDiv) {
const observer = new MutationObserver((mutationList, observer) => {
const _calciteElements = widgetDiv.querySelectorAll("[scale]");
_calciteElements.forEach((element: any) => {
if (element.scale !== measurementScale) {
element.scale = measurementScale;
}
});
});
observer.observe(widgetDiv, {childList: true, subtree: true});
}
});
});
}
},[mapView])
useEffect(() => {
// Perform final tasks after the t9n and config loads.
if (measurementLocalesT9n && measurementConfig && measurementScale && measurementLocale) {
// Set the component title
const t9n = measurementLocalesT9n && measurementLocalesT9n[measurementLocale as keyof typeof measurementLocalesT9n]? measurementLocalesT9n[measurementLocale as keyof typeof measurementLocalesT9n] as any: null;
measurementActionTitle = t9n? t9n?.title: "";
// Find all calcite elements and change their scale
const widgetDiv = document.getElementById(elementIDs.measurement_widgetDivID);
if (widgetDiv) {
const _calciteElements = widgetDiv.querySelectorAll("[scale]");
_calciteElements.forEach((element: any) => {
element.scale = measurementScale;
});
}
}
}, [measurementLocalesT9n, measurementConfig, measurementScale, measurementLocale]);
<CalcitePopover component-id={measurementConfig? measurementConfig.id: ""} id={elementIDs.measurement_popoverID} closable scale={measurementScale} label={measurementLocalesT9n? measurementLocalesT9n[measurementLocale as keyof typeof measurementLocalesT9n]?.title as string: ""} referenceElement={elementIDs.measurement_actionButtonID} placement="bottom-end" className={`measurement_popover__calcitepopover measurement_popover__calcitepopover--${measurementScale}`} heading={measurementLocalesT9n? measurementLocalesT9n[measurementLocale as keyof typeof measurementLocalesT9n]?.title: ""} onCalcitePopoverBeforeOpen={measurementPopover_onopen} onCalcitePopoverBeforeClose={measurementPopover_onclose}>
<div id={elementIDs.measurement_popoverDivID} className="measurement_popover__div">
<CalciteAction text="" icon="measure" scale={measurementScale} onClick={() => {measurement.current? measurement.current.activeTool = "distance": null}}></CalciteAction>
<CalciteAction text="" icon="measure-area" scale={measurementScale} onClick={() => {measurement.current? measurement.current.activeTool = "area": null}}></CalciteAction>
<CalciteAction text="" icon="measure-line" scale={measurementScale} onClick={() => {measurement.current? measurement.current.activeTool = "direct-line": null}}></CalciteAction>
<div id={elementIDs.measurement_widgetDivID}></div>
</div>
</CalcitePopover>
.measurement_popover__calcitepopover {
max-width: 600px;
}
.measurement_popover__calcitepopover--s .esri-widget,
.measurement_popover__calcitepopover--s h3.esri-widget__heading {
font-size: 0.9em;
}
.measurement_popover__calcitepopover--m .esri-widget,
.measurement_popover__calcitepopover--m h3.esri-widget__heading {
font-size: 1.1em;
}
.measurement_popover__calcitepopover--l .esri-widget,
.measurement_popover__calcitepopover--l h3.esri-widget__heading {
font-size: 1.3em;
}
After some trial and error I came up with the following. It is not perfect as some of the labels in the widget may not be calcite elements, however, this in combination with some CSS tricks will work.
The following is a basic example for the measurement widget. For the layerlist I used the VM and constructed it using Calcite components. I needed to manipulate it more than the widget could offer.
import type MeasurementWidget from "@arcgis/core/widgets/Measurement";
const measurement = useRef<MeasurementWidget>();
useEffect(() => {
if (mapView) {
Promise.all([
import('@arcgis/core/widgets/Measurement')
]).then(result => {
const MeasurementWidget = result[0].default;
measurement.current = new MeasurementWidget({
view: mapView,
container: elementIDs.measurement_widgetDivID
});
measurement.current.when().then((_measurement: MeasurementWidget) => {
// The Measurement Widget mutates after state change, therefore we cannot use reactiveUtils.
const widgetDiv = document.getElementById(elementIDs.measurement_widgetDivID);
if (widgetDiv) {
const observer = new MutationObserver((mutationList, observer) => {
const _calciteElements = widgetDiv.querySelectorAll("[scale]");
_calciteElements.forEach((element: any) => {
if (element.scale !== measurementScale) {
element.scale = measurementScale;
}
});
});
observer.observe(widgetDiv, {childList: true, subtree: true});
}
});
});
}
},[mapView])
useEffect(() => {
// Perform final tasks after the t9n and config loads.
if (measurementLocalesT9n && measurementConfig && measurementScale && measurementLocale) {
// Set the component title
const t9n = measurementLocalesT9n && measurementLocalesT9n[measurementLocale as keyof typeof measurementLocalesT9n]? measurementLocalesT9n[measurementLocale as keyof typeof measurementLocalesT9n] as any: null;
measurementActionTitle = t9n? t9n?.title: "";
// Find all calcite elements and change their scale
const widgetDiv = document.getElementById(elementIDs.measurement_widgetDivID);
if (widgetDiv) {
const _calciteElements = widgetDiv.querySelectorAll("[scale]");
_calciteElements.forEach((element: any) => {
element.scale = measurementScale;
});
}
}
}, [measurementLocalesT9n, measurementConfig, measurementScale, measurementLocale]);
<CalcitePopover component-id={measurementConfig? measurementConfig.id: ""} id={elementIDs.measurement_popoverID} closable scale={measurementScale} label={measurementLocalesT9n? measurementLocalesT9n[measurementLocale as keyof typeof measurementLocalesT9n]?.title as string: ""} referenceElement={elementIDs.measurement_actionButtonID} placement="bottom-end" className={`measurement_popover__calcitepopover measurement_popover__calcitepopover--${measurementScale}`} heading={measurementLocalesT9n? measurementLocalesT9n[measurementLocale as keyof typeof measurementLocalesT9n]?.title: ""} onCalcitePopoverBeforeOpen={measurementPopover_onopen} onCalcitePopoverBeforeClose={measurementPopover_onclose}>
<div id={elementIDs.measurement_popoverDivID} className="measurement_popover__div">
<CalciteAction text="" icon="measure" scale={measurementScale} onClick={() => {measurement.current? measurement.current.activeTool = "distance": null}}></CalciteAction>
<CalciteAction text="" icon="measure-area" scale={measurementScale} onClick={() => {measurement.current? measurement.current.activeTool = "area": null}}></CalciteAction>
<CalciteAction text="" icon="measure-line" scale={measurementScale} onClick={() => {measurement.current? measurement.current.activeTool = "direct-line": null}}></CalciteAction>
<div id={elementIDs.measurement_widgetDivID}></div>
</div>
</CalcitePopover>
.measurement_popover__calcitepopover {
max-width: 600px;
}
.measurement_popover__calcitepopover--s .esri-widget,
.measurement_popover__calcitepopover--s h3.esri-widget__heading {
font-size: 0.9em;
}
.measurement_popover__calcitepopover--m .esri-widget,
.measurement_popover__calcitepopover--m h3.esri-widget__heading {
font-size: 1.1em;
}
.measurement_popover__calcitepopover--l .esri-widget,
.measurement_popover__calcitepopover--l h3.esri-widget__heading {
font-size: 1.3em;
}