Sketch Widget API in Experience Builder Developer Edition not displaying graphics output

3359
7
Jump to solution
09-08-2020 07:39 AM
Henry_PeleshBW
Occasional Contributor

Hello all,

I am working to create a custom widget with the JS API Widget Wrapper by importing the Sketch widget into the "client/your-extensions/widgets" folder of my ArcGIS Experience Builder Application. The widget is working correctly, however, the resulting graphic is not visible when finishing a Sketch. A selection box is highlighted in my Map view but the physical graphic is not visible and cannot be rotated or modified (Image attached below). Please let me know of any possible solutions to this issue. 

Sketch output not showing graphic in custom Experience Builder widget.

Thanks,

Henry

0 Kudos
1 Solution

Accepted Solutions
GavinRehkemper
Esri Contributor

Hi Henry Pelesh, It looks like you've added a line:

const layer = new GraphicsLayer();

that is correct, it creates a GraphicsLayer, but you have not added that layer to the map. After that line you should add:

jmv.view.map.add(layer);

After you add that line, the drawn shape will stay visible on the map after you draw it.

View solution in original post

7 Replies
GavinRehkemper
Esri Contributor

Henry, could you please post your widget code that is not working so we can load it up to replicate your issue? Thanks!

0 Kudos
Henry_PeleshBW
Occasional Contributor
Here is my widget.tsx file:
/** @jsx jsx */
import { AllWidgetProps, BaseWidget, jsx, React } from "jimu-core";
import { IMConfig } from "../config";
import { JimuMapViewComponent, JimuMapView } from "jimu-arcgis";

import Sketch = require("esri/widgets/Sketch");
import GraphicsLayer = require("esri/layers/GraphicsLayer");
import { any } from "prop-types";

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

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

  constructor(props) {
    super(props);
    this.state = {
      jimuMapView: null,
      currentWidget: null
    };
  }

  activeViewChangeHandler = (jmv: JimuMapView) => {
    if (this.state.jimuMapView) {
      // 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();
      }
    }

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

      if (this.myRef.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);

        const layer = new GraphicsLayer();

        const sketch = new Sketch({
          layer: layer,
          view: jmv.view,
          container: container,
          creationMode: "update"

        });

        // Save reference to the "Current widget" in State so we can destroy later if necessary.
        this.setState({
          currentWidget: sketch
        });
      } else {
        console.error('could not find this.myRef.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();
      }
    }
  };

  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>
    );
  }
}
Thank you,
Henry
0 Kudos
Henry_PeleshBW
Occasional Contributor

Gavin Rehkemper‌ has there been any progress on this? I appreciate you taking the time to help. Please let me know if there is anything more I can provide you with to help solve my issue.

Thanks,

Henry

0 Kudos
GavinRehkemper
Esri Contributor

Hi Henry Pelesh, It looks like you've added a line:

const layer = new GraphicsLayer();

that is correct, it creates a GraphicsLayer, but you have not added that layer to the map. After that line you should add:

jmv.view.map.add(layer);

After you add that line, the drawn shape will stay visible on the map after you draw it.

Henry_PeleshBW
Occasional Contributor

Gavin Rehkemper‌,

Thank you very much! I must have missed that line of code. I appreciate your help! Problem solved!

Regards,

Henry

0 Kudos
RenattoAttiêLima
New Contributor

Good afternoon GavinRehKemper.

Can you help me ?

I needed implement this code and I wrote this code with your clue.

But the widget does not show on the screen and doesn't return error.

0 Kudos
RenattoAttiêLima
New Contributor

this code is...

 

/** @jsx jsx */
import { React, AllWidgetProps, BaseWidget, jsx, React  } from "jimu-core";
import { Tabs, Tab, Label, Card, CardHeader, CardBody, CardFooter, Switch, Input, Row, Col, Form, FormGroup, Container, Button  } from 'jimu-ui'
import { TrashOutlined } from 'jimu-icons/outlined/editor/trash'
import { JimuMapViewComponent, JimuMapView } from "jimu-arcgis";
import Sketch = require("esri/widgets/Sketch");
import GraphicsLayer = require("esri/layers/GraphicsLayer");
import { any } from "prop-types";



import "../css/style.css"
import { CardImg, CardTitle } from "reactstrap/lib";



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

    state = {
      jimuMapView: null,
      currentWidget: null,
      switch : false,
      layersOnMap: []

    }
 

   activeViewChangeHandler = (jmv: JimuMapView) => {
    alert('aqui')
    if (this.state.jimuMapView) {
      if (this.state.currentWidget) {
        this.state.currentWidget.destroy();
      }
    }
    if (jmv) {
      this.setState({
        jimuMapView: jmv as JimuMapView
      });
      if (this.myRef.current) {
        //const container = document.createElement("div");
        //this.myRef.current.appendChild(container);
        const layer = new GraphicsLayer();
        jmv.view.map.add(layer);
 
        const sketch = new Sketch({
          layer: layer,
          view: jmv.view,
          container: document.createElement("div"),
          creationMode: "update"
        });

        jmv.view.ui.add(sketch, "top-right");
     

        this.setState({
          currentWidget: sketch
        });
      } else {
        console.error('could not find this.myRef.current');
      }
    }
  };


  componentDidUpdate = evt => {
    if (this.props.useMapWidgetIds.length === 0) {
      if (this.state.currentWidget) {
        this.state.currentWidget.destroy();
      }
    }
  };  


    render() {    

    let jmc = <p>Please select a map.</p>;
    if (
      this.props.hasOwnProperty("useMapWidgetIds") &&
      this.props.useMapWidgetIds &&
      this.props.useMapWidgetIds[0]
    ) {
      alert('jmc')

      jmc = (
        <JimuMapViewComponent
          useMapWidgetIds={this.props.useMapWidgetIds}
          onActiveViewChange={this.activeViewChangeHandler}
        />
      );
       
      return (
      <Container fluid>
        <Row>
          <Col>
            <Tabs
            defaultValue="tab-1"
            onChange={function noRefCheck(){}}
            onClose={function noRefCheck(){}}        
        >          
                <Tab className="tab-select" id="tab-1" title="Atual">  
                    <div width="100%" >
                        <Card>
                            <CardBody>
                                <Label className="menu" size="default"><TrashOutlined /> Apagar Seleção</Label> <br/>
                                <Label className="menu" size="default">
                                  <div className="widget-js-api-widget-wrapper jimu-widget" >
                                    <div  ref={this.myRef}></div>
                                    {jmc}
                                  </div>
                              </Label>
                            </CardBody>
                            <CardFooter className="d-flex justify-content-between">
                                <Label size="default">

                                    <Switch
                                        aria-label="Switch"
                                        checked={this.state.switch}
                                        onClick={() => this.setState({ switch: !this.state.switch })}
                                    />                                  
                                    Habilitar Streaming
                                 </Label>
                            </CardFooter>
                        </Card>
                    </div>
                </Tab>
                <Tab className="tab-select" id="tab-2" title="Histórica">  
                    <div width="100%" >
                        <Card>
                            <CardHeader>
                                <Label className="menu" size="default"><TrashOutlined /> Apagar Seleção</Label> <br/>
                                <Label className="menu" size="default">
                                  <div className="widget-js-api-widget-wrapper jimu-widget" style={{ overflow: "auto" }}>
                                    <div className="here" ref={this.myRef}></div>
                                    {jmc}
                                  </div>
                              </Label>                                
                            </CardHeader>
                            <CardBody>
                            <Form>
                            <FormGroup>

                                <Row>
                                  <Col sm="12">
                                      <Input id="busca_datas_hist"  name="busca_datas_hist" placeholder="<i class='icon-search'></i>" type="search" />                                    
                                  </Col>
                                </Row>
                              </FormGroup>
                              <FormGroup>
                                <Row>
                                  <Col sm="6">
                                  <Label for="datas_historicas">Datas</Label>  
                                  <br/>                              
                                    <Input id="datas_historicas"  multiple name="datas_historicas"  type="select" className="lista_datas">
                                          <option>30/08/2022</option>
                                          <option>29/08/2022</option>
                                          <option>28/08/2022</option>
                                    </Input>
                                  </Col>
                                  <Col sm="6">
                                    <CardTitle tag="h5">Miniatura</CardTitle>                                    
                                    <CardImg  alt="Card image cap" src="https://picsum.photos/318/180"  top width="100%"/>                                    
                                  </Col>
                                  </Row>      
                                  </FormGroup>
                              </Form>                        
                            </CardBody>
                            <CardFooter className="d-flex justify-content-between">
                            <Button className="botao_sucesso">Adicionar ao Mapa</Button>
                            </CardFooter>
                        </Card>
                    </div>
                </Tab>                                
            </Tabs>
            </Col>
            </Row>        
          </Container>  
      );
    }

}


0 Kudos