-
Notifications
You must be signed in to change notification settings - Fork 0
Custom UI Sample React Native
Hudson_BuildService edited this page Jan 9, 2026
·
1 revision
const HomeView = () => {
const [dialogHidden, setDialogHidden] = useState(true);
const [config, setConfig] = useState({});
useEffect(() => {
async function runAsync() {
const configuredServers = await ServerSdk.getServers();
const servers: IServerModel[] = [];
for (const server of configuredServers) {
servers.push(server);
}
if (servers.length !== 0 && servers[0] != null) {
const { serverId } = servers[0];
TriggerSdk.setCallback(serverId, <PorgramKey>);
await TriggerSdk.triggerDownload(serverId, <PorgramKey>);
}
}
runAsync();
}, []);
useEffect(() => {
const webview: EmitterSubscription = TriggerManager.setOnWebSurveyStart(onWebSurvey);
const surveyStart: EmitterSubscription = TriggerManager.setOnSurveyStart(onSurveyStart);
const scenarioLoad: EmitterSubscription = TriggerManager.setOnScenarioLoad(onScenarioLoad);
const scenarioError: EmitterSubscription = TriggerManager.setOnScenarioError(onScenarioError);
return () => {
webview.remove();
surveyStart.remove();
scenarioLoad.remove();
scenarioError.remove();
};
});
const onWebSurvey = (events: IWebSurveyModel) => {
// Show web survey
};
const onSurveyStart = (events: ISurveyModel) => {
const { serverId, programKey, surveyId } = events;
const customData = {};
const respondentValues = {};
SurveySdk.startSurvey(serverId, programKey, surveyId, customData, respondentValues);
setDialogHidden(false);
setConfig(events);
};
const onScenarioLoad = (events: IScenarioCallback) => {
// on scenario script starts
};
const onScenarioError = (events: IScenarioCallback) => {
// when scenario scripting contains error
};
const onDialogCloseAction = () => {
setDialogHidden(true);
};
return (
<View style={{ flex: 1 }}>
<DialogView hidden={dialogHidden} onClose={onDialogCloseAction} config={config} />
</View>
);
};
export default HomeView;
const SurveyDialogView = (props: IDialogViewProps) => {
const [infos, setInfos] = useState<IDefaultQuestion[]>([]);
const [showFinished, setShowFinished] = useState<IFinishedConfig>({ finished: false, message: '' });
const [pageControl, setPageControl] = useState<PageControl>();
const onSurveyQuit = (_: { [key: string]: string }) => {
// Survey quit by user
props.onClose();
};
const onSurveyErrored = async (_: ISurveyErrored) => {
// Survey contains error
setShowFinished({
finished: true,
message: 'Sorry an error happen'
});
};
const onSurveyFinished = async (_: ISurveyFinished) => {
// Survey completed
setShowFinished({
finished: true,
message: 'Thank you!'
});
};
const onSurveyPageReady = async (control: PageControl) => {
setShowFinished({
finished: false,
message: ''
});
// Set visibilities for navigation buttons
setPageControl(control);
// Fetch all questions for the page
const questions = await control.getQuestion();
setInfos(questions);
};
useEffect(() => {
const pageReady: EmitterSubscription = SurveyFrameManager.setOnSurveyPageReady(onSurveyPageReady);
const finished: EmitterSubscription = SurveyFrameManager.setOnSurveyFinished(onSurveyFinished);
const errored: EmitterSubscription = SurveyFrameManager.setOnSurveyErrored(onSurveyErrored);
const quit: EmitterSubscription = SurveyFrameManager.setOnSurveyQuit(onSurveyQuit);
return () => {
pageReady.remove();
finished.remove();
errored.remove();
quit.remove();
};
});
const onCloseAction = async () => {
if (!pageControl) {
return;
}
if (!showFinished.finished) {
await pageControl.quit(true);
} else {
props.onClose();
}
};
const onBackAction = async () => {
if (!pageControl) {
return;
}
await pageControl.back();
};
const onNextAction = async () => {
if (!pageControl) {
return;
}
await pageControl.next();
};
const renderFinishedPage = () => {
return (
<View>
<Text style={styles.title}>{showFinished.message}</Text>
</View>
);
};
const renderQuestion = () => {
if (!pageControl) {
return [];
}
const elements: JSX.Element[] = [];
// Loop through question in current survey page, and generate Views
for (const info of infos) {
switch (info.nodeType) {
// If question type is TEXT
case NodeType.Text: {
// PageControl is passed to the question
// 1. to fetch the current answers set
// 2. Interaction like answering question
elements.push(<QuestionTextView key={info.id} info={info} pageControl={pageControl} />);
break;
}
// ... More question type intergrations
}
}
return elements;
};
const render = () => {
if (props.hidden || !pageControl) {
return <View />;
}
return (
<View style={styles.container}>
<View style={styles.topView}>
<Button title={'Close'} color={'#ff0000'} onPress={onCloseAction} />
</View>
<View style={styles.fillView}>
<View style={{ display: showFinished.finished ? 'flex' : 'none', justifyContent: 'center', alignItems: 'center' }}>{renderFinishedPage()}</View>
<ScrollView style={{ paddingHorizontal: 16, display: showFinished.finished ? 'none' : 'flex' }}>{renderQuestion()}</ScrollView>
</View>
<View style={styles.bottomView}>
<View>{!showFinished.finished && pageControl.showBackward && <Button onPress={onBackAction} title={pageControl.backwardText} />}</View>
<View>{!showFinished.finished && pageControl.showForward && <Button onPress={onNextAction} title={pageControl.forwardText} />}</View>
</View>
</View>
);
};
return render();
};
export default SurveyDialogView;
const styles = StyleSheet.create({
container: {
position: 'absolute',
top: 0,
bottom: 0,
left: 0,
right: 0,
flex: 1,
flexDirection: 'column',
justifyContent: 'space-between',
alignItems: 'stretch',
backgroundColor: '#fff'
},
topView: {
padding: 16,
justifyContent: 'center',
alignItems: 'flex-end'
},
bottomView: {
padding: 16,
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center'
},
fillView: {
flex: 1,
justifyContent: 'flex-start',
alignItems: 'stretch'
},
title: {
fontSize: 16,
color: '#000000',
fontWeight: '500',
justifyContent: 'center',
alignItems: 'center'
}
});
const QuestionTextView = (props: IQuestionProps) => {
const styles = require('../utils/styles');
const [text, setText] = useState('');
const { pageControl } = props;
useEffect(() => {
async function fetchData() {
// 1. fetch the current answer that is set and display it
const answer = await pageControl.getText(props.info.id);
setText(answer);
}
fetchData();
}, [pageControl, props.info.id]);
const onChangeText = async (text: string) => {
setText(text);
// 2. set the result to the question
await pageControl.setText(props.info.id, text);
};
return (
<View key={props.info.id} style={styles.questionBottom}>
<Text style={styles.questionTitle}>{props.info.title}</Text>
<ErrorTextView errors={props.info.errors} />
<TextInput
value={text}
multiline={true}
numberOfLines={4}
textAlignVertical={'top'}
style={{ padding: 10, borderRadius: 8, borderColor: '#000000', borderWidth: 1 }}
onChangeText={onChangeText}
/>
</View>
);
};
export default QuestionTextView;Copyright © 2026 Forsta. All rights reserved.
- Initializing the SDK
- Download a Program
- Sending App Events
- Sending Journey Log
- Survey Triggering
- Displaying a Survey
- Forsta Plus Server
- Program Lifecycle Monitoring
- Starting and Updating a Program
- Advanced Trigger Control