Select to view content in your preferred language

Survey123 Javascript Embed with react

782
2
01-24-2023 10:35 AM
ankoure_Cambridge
New Contributor

Hello All, 

I am looking to create a custom web application with the ArcGIS 4.x JS API with React. I would like to embed a Survey123 form to collect data from Users similar to the Survey Widget in Experience Builder. 

Is it possible to integrate the Survey123 API as shown here: https://developers.arcgis.com/survey123/guide/embed-a-survey-using-javascript/#configure-a-survey-in...with this repo using the "@arcgis/core" with React and Vite? https://github.com/Esri/jsapi-resources/tree/main/esm-samples/jsapi-react 

 

Or should I approach this a different way? Ideally I am looking to have the form load conditionally (i.e only when 1 layer is clicked on). I also am trying to pass(some) data from the clicked on layer to the Survey form. 

All the Best, 

Andrew

2 Replies
bradMaps
Occasional Contributor

I'm trying to do something similar.  I'm actually trying to integrate the S123 API with this newer sample by @ReneRubalcavahttps://github.com/odoe/ds2024-arcgis-map-comps-next/ .  Were you able to figure this out?

0 Kudos
AidanDonnelly
Emerging Contributor

I was able to get this (sort of) working using Ionic and React - using Next might prove to be a bit more challenging though with default SSR and all that.  

const SurveyPage: React.FC = () => {
  const containerRef = useRef<HTMLDivElement>(null);
  const { isSignedIn, portal } = useAuth();

  useEffect(() => {
    // Run script loading and survey initialization only when signed in.
    if (!isSignedIn) return;

    // Function to load the Survey123 script dynamically
    const loadSurveyScript = () => {
      return new Promise<void>((resolve, reject) => {
        // If already loaded, resolve immediately.
        if ((window as any).Survey123WebForm) {
          resolve();
          return;
        }
        const script = document.createElement('script');
        script.src="https://survey123.arcgis.com/api/jsapi/";
        script.onload = () => resolve();
        script.onerror = () => reject(new Error("Failed to load Survey123 API"));
        document.head.appendChild(script);
      });
    };

    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    let surveyInstance: any;
    loadSurveyScript()
      .then(() => {
        // Ensure the container exists and the Survey123WebForm global is available
        if (containerRef.current && (window as any).Survey123WebForm) {
          // Clear the container to avoid duplicate surveys
          containerRef.current.innerHTML = "";
          surveyInstance = new (window as any).Survey123WebForm({
            clientId: ArcGISConfig.auth.clientId,
            container: containerRef.current,
            itemId: "******",
            // eslint-disable-next-line @typescript-eslint/ban-ts-comment
            //@ts-expect-error
            token: portal?.credential.token,
          });
        }
      })
      .catch((error) => {
        console.error("Survey123 script failed to load:", error);
      });

    // Cleanup on unmount
    return () => {
      if (containerRef.current) {
        containerRef.current.innerHTML = "";
      }
    };
  }, [isSignedIn, portal]);

  return (
    <IonPage>
      <IonHeader>
        <IonToolbar>
          <IonButtons slot="start">
            <IonMenuButton />
          </IonButtons>
          <IonTitle>Survey</IonTitle>
        </IonToolbar>
      </IonHeader>

      <IonContent fullscreen>

        {/* Container for the Survey123 form */}
        {isSignedIn && <div ref={containerRef} id="formDiv" style={{ padding: '16px', height: '100vh' }} />}
      </IonContent>
    </IonPage>
  );
};

export default SurveyPage;


Have you found a better solution?  I don't really like how 'non-Reactive' this is.

Thanks,


 

Aidan

0 Kudos