Select to view content in your preferred language

Change LayerList Widget Scale

383
1
Jump to solution
03-05-2024 12:45 PM
René_Ténière
Frequent Contributor

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é

0 Kudos
1 Solution

Accepted Solutions
René_Ténière
Frequent Contributor

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;
}

 

 

 

View solution in original post

0 Kudos
1 Reply
René_Ténière
Frequent Contributor

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;
}

 

 

 

0 Kudos