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
I'm trying to do something similar. I'm actually trying to integrate the S123 API with this newer sample by @ReneRubalcava: https://github.com/odoe/ds2024-arcgis-map-comps-next/ . Were you able to figure this out?
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