Build a multi-question survey with different question types — text input, single-select radio buttons, multi-select checkboxes, star rating, and scale slider. Store survey structure in a Firestore questions subcollection with a questionType field. Render each question dynamically using Conditional Builder based on type. Collect responses in a Page State Map and submit to a survey_responses collection. Show a progress indicator and validate required questions before advancing.
Building a Multi-Type Survey in FlutterFlow
Surveys need different question types for different data. Unlike a quiz with only multiple choice, surveys use text fields, dropdowns, checkboxes, ratings, and scales. This tutorial builds a flexible survey system that renders questions dynamically from Firestore and handles all common question types.
Prerequisites
- A FlutterFlow project with Firestore configured
- A surveys collection and questions subcollection in Firestore
- Understanding of Conditional Builder and Page State in FlutterFlow
Step-by-step guide
Create the Firestore data model with typed question documents
Create the Firestore data model with typed question documents
Create a surveys collection with fields: title (String), description (String). Create a questions subcollection with fields: questionText (String), questionType (String enum: text, radio, checkbox, rating, slider), options (String Array, for radio/checkbox types), isRequired (Boolean), order (int), placeholder (String, for text type). Add 5-6 test questions with different types to verify rendering.
Expected result: Firestore has a surveys collection with a questions subcollection containing various question types.
Build the survey page with PageView and dynamic question rendering
Build the survey page with PageView and dynamic question rendering
Create a SurveyPage with Route Parameter surveyId. Add a Backend Query for the questions subcollection ordered by the order field. Add a PageView with page snapping and disabled swiping (NeverScrollableScrollPhysics). For each question page, add a Conditional Builder that checks questionType: if 'text' → render TextField, if 'radio' → render RadioButtonGroup with options, if 'checkbox' → render CheckboxGroup, if 'rating' → render a star rating Row, if 'slider' → render Slider.
Expected result: Each survey question page renders the appropriate input widget based on questionType.
Collect responses in a Page State Map keyed by question ID
Collect responses in a Page State Map keyed by question ID
Add a Page State variable called responses (JSON type). On each input widget's On Changed action, update the responses Map: set the key as the question document ID and the value as the answer (string for text, selected option index for radio, list for checkbox, number for rating/slider). This collects all responses in one structured object. Access via responses[questionId] to check if a specific question has been answered.
Expected result: The responses Map accumulates answers as the user progresses through questions.
Validate required questions and show progress
Validate required questions and show progress
Add a LinearPercentIndicator at the top bound to currentIndex / totalQuestions. On the Next button tap, check if the current question has isRequired true and if responses[currentQuestionId] is empty. If required and empty, show a Snackbar error 'This question is required.' and block navigation. If answered or not required, animate to the next page. On the last page, change button text to 'Submit'.
Expected result: Required questions block advancement until answered, and progress updates with each completed question.
Submit responses to Firestore and show a thank-you screen
Submit responses to Firestore and show a thank-you screen
On Submit button tap, create a document in survey_responses collection with fields: surveyId, userId (current user or anonymous device ID), responses (the Map), submittedAt (timestamp). Navigate to a thank-you page or show a success dialog. Optionally trigger a Cloud Function on new response documents to send a Slack notification or aggregate results.
Expected result: Survey responses are saved to Firestore with user identification and timestamps.
Complete working example
1FIRESTORE DATA MODEL:2 surveys/{surveyId}3 title: String4 description: String5 └── questions/{questionId}6 questionText: String7 questionType: "text" | "radio" | "checkbox" | "rating" | "slider"8 options: ["Option A", "Option B", "Option C"] (radio/checkbox only)9 isRequired: Boolean10 order: int11 placeholder: String (text only)1213PAGE STATE:14 currentIndex: int = 015 responses: JSON Map = {}1617WIDGET TREE:18 Column19 ├── LinearPercentIndicator (percent: currentIndex / total)20 ├── Expanded21 │ └── PageView (horizontal, NeverScrollableScrollPhysics)22 │ └── Per question:23 │ Column24 │ ├── Text (questionText, Headline Small)25 │ ├── SizedBox (20)26 │ └── Conditional Builder (questionType)27 │ ├── "text" → TextField (maxLines: 3, placeholder)28 │ ├── "radio" → RadioButtonGroup (options)29 │ ├── "checkbox" → CheckboxGroup (options)30 │ ├── "rating" → Row of 5 Star Icons31 │ └── "slider" → Slider (min 1, max 10)32 └── Button ("Next" / "Submit")33 On Tap:34 1. If isRequired && !responses.has(questionId) → Show Error Snackbar35 2. Else if not last → Animate Next Page + increment currentIndex36 3. Else → Create Document survey_responses → Thank You3738SURVEY RESPONSES DOCUMENT:39 surveyId: String40 userId: String41 responses: { "questionId1": "answer", "questionId2": 4, ... }42 submittedAt: TimestampCommon mistakes when creating a Custom Survey Widget for Your FlutterFlow App
Why it's a problem: Not validating required questions before allowing navigation to the next question
How to avoid: Check the isRequired flag on each question. Block the Next button and show an error if a required question has no response.
Why it's a problem: Using App State instead of Page State for survey responses
How to avoid: Use Page State for in-progress survey data so responses reset when the user leaves the page.
Why it's a problem: Loading all question responses into a flat List instead of a keyed Map
How to avoid: Use a JSON Map with question document IDs as keys. This makes responses robust to question order changes.
Best practices
- Use a Firestore data model with questionType field for flexible question rendering
- Render inputs dynamically with Conditional Builder based on questionType
- Collect responses in a keyed Map (questionId → answer) for reliable data
- Validate required questions before allowing navigation
- Show a progress indicator so respondents know how many questions remain
- Store responses with surveyId and userId for analytics and filtering
- Use Page State (not App State) for in-progress survey data to prevent stale responses
Still stuck?
Copy one of these prompts to get a personalized, step-by-step explanation.
I want to build a multi-type survey in FlutterFlow with text, radio, checkbox, rating, and slider question types loaded from Firestore. Explain the data model, dynamic rendering with Conditional Builder, response collection in a Map, and submission to Firestore.
Create a page with a progress bar at top, a large question text area, an area below for the answer input (I will add different input types), and a Next button at the bottom.
Frequently asked questions
Can I add conditional logic (show question B only if question A answer is X)?
Yes but it requires custom logic. Add a showIf field to question documents with a condition (dependsOnQuestionId, expectedValue). Check this in the rendering logic with Conditional Visibility.
How do I analyze survey results?
Query the survey_responses collection and aggregate responses per question. Use a Cloud Function to compute averages, counts, and percentages, or export to a spreadsheet.
Can I create anonymous surveys without user login?
Yes. Skip the userId field or use a device identifier from Global Properties. Set Firestore security rules to allow anonymous writes to survey_responses.
How do I prevent duplicate survey submissions?
On page load, query survey_responses for the current userId + surveyId. If a document exists, redirect to a 'You already completed this survey' page.
Can I add an image to survey questions?
Yes. Add an imageUrl field to question documents. Display an Image widget above the question text with Conditional Visibility for when imageUrl is not empty.
Can RapidDev help build a survey platform?
Yes. RapidDev can build survey platforms with conditional logic, branching paths, result dashboards, export features, and multi-language support.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation