Skip to content
This repository has been archived by the owner on Jan 25, 2022. It is now read-only.

Commit

Permalink
functional and v1.4 updates
Browse files Browse the repository at this point in the history
  • Loading branch information
gavinr-maps committed May 3, 2021
1 parent 7ee392d commit 11df603
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 102 deletions.
6 changes: 2 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,8 @@ The main example here includes the [2D Measurement widget](https://developers.ar
1. Make sure *both* scripts are running (in the `server` folder and `client`) folder).
1. Every time you make a change to your widget, it will be re-built with webpack automatically.

## Icon Widget

If you want to include a widget that is primarily placed as an icon over the map (using `view.ui.add()`), like the [Compass widget](https://developers.arcgis.com/javascript/latest/sample-code/widgets-compass-2d/index.html), an example is shown in the [compass branch here](https://github.com/gavinr/js-api-widget-wrapper-experience-builder/tree/compass) ([download zip](https://github.com/gavinr/js-api-widget-wrapper-experience-builder/archive/compass.zip)). This will be a less-common use case for custom widgets, because the out-of-the-box Experience Builder Map Widget allows you to easily enable/disable these types of widgets in the widget settings.

## More

View my other Experience Builder projects [here](https://github.com/gavinr?tab=repositories&q=experience-builder).

View another example of using a JS API widget within Experience Builder [here](https://developers.arcgis.com/experience-builder/sample-code/widgets/js-api-widget/) and [here](https://developers.arcgis.com/experience-builder/sample-code/widgets/editor/).
4 changes: 2 additions & 2 deletions widgets/js-api-widget-wrapper/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
"name": "js-api-widget-wrapper",
"label": "JS API Wrapper",
"type": "widget",
"version": "1.0.0",
"version": "1.4.0",
"dependency": "jimu-arcgis",
"exbVersion": "1.0.0",
"exbVersion": "1.4.0",
"author": "Gavin Rehkemper, Esri",
"description": "Example of an Experience Builder widget that can wrap any ArcGIS API for JavaScript widget.",
"license": "http:https://www.apache.org/licenses/LICENSE-2.0",
Expand Down
109 changes: 43 additions & 66 deletions widgets/js-api-widget-wrapper/src/runtime/widget.tsx
Original file line number Diff line number Diff line change
@@ -1,97 +1,74 @@
/** @jsx jsx */
import { AllWidgetProps, BaseWidget, jsx, React } from "jimu-core";
import { IMConfig } from "../config";
import { AllWidgetProps, jsx, React } from "jimu-core";
import { JimuMapViewComponent, JimuMapView } from "jimu-arcgis";
const { useRef, useState, useEffect } = React;

import DistanceMeasurement2D = require("esri/widgets/DistanceMeasurement2D");
import * as DistanceMeasurement2D from "esri/widgets/DistanceMeasurement2D";

interface IState {
jimuMapView: JimuMapView;
currentWidget: DistanceMeasurement2D;
}

export default class Widget extends BaseWidget<AllWidgetProps<IMConfig>, any> {
private myRef = React.createRef<HTMLDivElement>();

constructor(props) {
super(props);
this.state = {
jimuMapView: null,
currentWidget: null
};
}
export default function Setting(props: AllWidgetProps<any>) {
const widgetRef = useRef<HTMLDivElement>();
const [currentWidget, setCurrentWidget] = useState<DistanceMeasurement2D>();

activeViewChangeHandler = (jmv: JimuMapView) => {
if (this.state.jimuMapView) {
const activeViewChangeHandler = (jmv: JimuMapView) => {
if (currentWidget && currentWidget !== undefined) {
// we have a "previous" map where we added the widget
// (ex: case where two Maps in single Experience page and user is switching
// between them in the dropdown) - we must destroy the old widget in this case.
if (this.state.currentWidget) {
this.state.currentWidget.destroy();
}
currentWidget.destroy();
}

if (jmv) {
this.setState({
jimuMapView: jmv
});

if(this.myRef.current) {
if (widgetRef.current) {
// since the widget replaces the container, we must create a new DOM node
// so when we destroy we will not remove the "ref" DOM node
const container = document.createElement("div");
this.myRef.current.appendChild(container);
widgetRef.current.appendChild(container);

const distanceMeasurement2D = new DistanceMeasurement2D({
view: jmv.view,
container: container
});

// Save reference to the "Current widget" in State so we can destroy later if necessary.
this.setState({
currentWidget: distanceMeasurement2D
});
setCurrentWidget(distanceMeasurement2D);
} else {
console.error('could not find this.myRef.current');
console.error('could not find widgetRef.current');
}
}
};

// activeViewChangeHandler is not called in the builder when "None" is selected
// for the map, so we must cleanup here:
componentDidUpdate = evt => {
if (this.props.useMapWidgetIds.length === 0) {
// "None" was selected in the "Select map widget" dropdown:
if (this.state.currentWidget) {
this.state.currentWidget.destroy();
}
useEffect(() => {
if (props.useMapWidgetIds && props.useMapWidgetIds.length === 0 && currentWidget) {
console.log('destroying');
currentWidget.destroy();
}
};
});

render() {
// If the user has selected a map, include JimuMapViewComponent.
// If not, show a message asking for the Experience Author to select it.
let jmc = <p>Please select a map.</p>;
if (
this.props.hasOwnProperty("useMapWidgetIds") &&
this.props.useMapWidgetIds &&
this.props.useMapWidgetIds.length === 1
) {
jmc = (
<JimuMapViewComponent
useMapWidgetIds={this.props.useMapWidgetIds}
onActiveViewChange={this.activeViewChangeHandler}
/>
);
}

return (
<div
className="widget-js-api-widget-wrapper jimu-widget"
style={{ overflow: "auto" }}
>
<div className="here" ref={this.myRef}></div>
{jmc}
</div>
// If the user has selected a map, include JimuMapViewComponent.
// If not, show a message asking for the Experience Author to select it.
let jmc = <p>Please select a map.</p>;
if (
props.hasOwnProperty("useMapWidgetIds") &&
props.useMapWidgetIds &&
props.useMapWidgetIds.length === 1
) {
jmc = (
<JimuMapViewComponent
useMapWidgetId={props.useMapWidgetIds?.[0]}
onActiveViewChange={activeViewChangeHandler}
/>
);
}

return (
<div
className="widget-js-api-widget-wrapper jimu-widget"
style={{ overflow: "auto" }}
>
<div ref={widgetRef}></div>
{jmc}
</div>
);
}
54 changes: 24 additions & 30 deletions widgets/js-api-widget-wrapper/src/setting/setting.tsx
Original file line number Diff line number Diff line change
@@ -1,40 +1,34 @@
import { React, FormattedMessage } from "jimu-core";
import { BaseWidgetSetting, AllWidgetSettingProps } from "jimu-for-builder";
import { IMConfig } from "../config";
import { React } from "jimu-core";
import { AllWidgetSettingProps } from "jimu-for-builder";
import defaultMessages from "./translations/default";
import {
JimuMapViewSelector,
SettingSection,
SettingRow
} from "jimu-ui/setting-components";
} from "jimu-ui/advanced/setting-components";

export default class Setting extends BaseWidgetSetting<
AllWidgetSettingProps<IMConfig>,
any
> {
onMapWidgetSelected = (useMapWidgetIds: string[]) => {
this.props.onSettingChange({
id: this.props.id,
export default function Setting(props: AllWidgetSettingProps<any>) {

const onMapWidgetSelected = (useMapWidgetIds: string[]) => {
props.onSettingChange({
id: props.id,
useMapWidgetIds: useMapWidgetIds
});
};

render() {
return (
<div className="widget-setting-js-api-widget-wrapper">
<SettingSection
className="map-selector-section"
title={this.props.intl.formatMessage({
id: "selectMapWidget",
defaultMessage: defaultMessages.selectMapWidget
})}
>
<JimuMapViewSelector
onSelect={this.onMapWidgetSelected}
useMapWidgetIds={this.props.useMapWidgetIds}
/>
</SettingSection>
</div>
);
}
return (
<div className="widget-setting-js-api-widget-wrapper">
<SettingSection
className="map-selector-section"
title={props.intl.formatMessage({
id: "selectMapWidget",
defaultMessage: defaultMessages.selectMapWidget
})}
>
<JimuMapViewSelector
onSelect={onMapWidgetSelected}
useMapWidgetIds={props.useMapWidgetIds}
/>
</SettingSection>
</div>
);
}

0 comments on commit 11df603

Please sign in to comment.