Build a survey with conditional branching using a PageView where each page renders a different question type based on a Firestore questions subcollection. Each question document includes a conditionalNext map that routes users to a specific question order based on their answer. Responses are collected in a Page State Map keyed by questionId, and the progress bar adapts to the expected remaining path rather than total question count. On submit, responses are saved to a survey_responses collection.
Building a Branching Survey in FlutterFlow
This tutorial creates a survey system where questions branch based on user answers. Unlike a linear quiz, selecting a specific option can skip irrelevant questions or dive deeper into a topic. Each question supports different input types: single choice, multiple choice, text, rating, and scale. The progress bar adapts to the current branch path so users always see accurate completion estimates. This pattern is used in intake forms, diagnostic tools, customer feedback, and onboarding questionnaires.
Prerequisites
- A FlutterFlow project with Firestore configured
- A surveys collection and questions subcollection in Firestore
- Basic understanding of PageView and Conditional Visibility in FlutterFlow
- Familiarity with Page State variables
Step-by-step guide
Design the Firestore data model for surveys with conditional questions
Design the Firestore data model for surveys with conditional questions
Create a surveys collection with fields: title (String), description (String), questionCount (int), createdBy (String). Under each survey document, create a questions subcollection with fields: questionText (String), type (String: singleChoice, multiChoice, text, rating, scale), options (String array, used for choice types), isRequired (bool), order (int), conditionalNext (Map: keys are option indexes as strings, values are the target question order numbers). For example, if question 2 has conditionalNext {"0": 5, "1": 3}, selecting option 0 jumps to question order 5 while option 1 goes to question order 3. Create a survey_responses collection with fields: surveyId (String), userId (String), responses (Map of questionId to answer), completedAt (Timestamp).
Expected result: Firestore has surveys with branching question definitions and a response storage collection.
Build the survey page with a PageView and adaptive progress bar
Build the survey page with a PageView and adaptive progress bar
Create a SurveyPage with Route Parameter surveyId. Add a Backend Query for the questions subcollection ordered by order ascending. Store all questions in Page State questionList (Document List). Add Page State: currentQuestionIndex (int, tracking position in questionList), responses (Map, keyed by questionId), questionPath (int List, tracking which question orders the user has visited). At the top, display a LinearPercentIndicator where the percent is calculated from the current path position relative to the estimated total remaining questions in the current branch. Below, add a PageView with NeverScrollableScrollPhysics.
Expected result: A survey page loads with an adaptive progress bar and a PageView ready for question rendering.
Render different question types using Conditional Builder
Render different question types using Conditional Builder
Inside each PageView page, add a Column with the questionText in Headline Small style. Below, use a Conditional Builder (or stacked Conditional Visibility containers) that checks the question type field. For singleChoice: display a RadioButton group bound to options. For multiChoice: display a CheckboxGroup. For text: display a multiline TextField. For rating: display a row of 5 star IconButtons. For scale: display a Slider from 1 to 10. When the user selects or enters a value, update the responses Map in Page State with the questionId as key and the answer as value.
Expected result: Each question renders the correct input widget based on its type, and answers are stored in the responses Map.
Implement conditional branching navigation on the Next button
Implement conditional branching navigation on the Next button
Add a Next button below the question area. On tap, first validate that required questions have an answer (check isRequired and responses Map). Then check if the current question has a conditionalNext map with a matching key for the selected answer index. If a match exists, find the question in questionList with the matching order value and animate the PageView to that page index. If no conditional match exists, go to the next sequential question. Append the visited question order to questionPath for back-navigation support. On the last reachable question, change the button to Submit.
Expected result: Selecting specific answers routes users to different questions, skipping irrelevant ones.
Save survey responses to Firestore on submission
Save survey responses to Firestore on submission
When the user taps Submit on the final question, create a document in survey_responses with surveyId, userId (current user), responses Map (the complete Page State responses), and completedAt (server timestamp). Navigate to a ThankYouPage showing a confirmation message, the number of questions answered, and an optional summary of their responses. Add a Back button that returns to the survey list.
Expected result: Survey responses are saved to Firestore and the user sees a confirmation screen.
Complete working example
1FIRESTORE DATA MODEL:2 surveys/{surveyId}3 title: String4 description: String5 questionCount: int6 createdBy: String7 └── questions/{questionId}8 questionText: String9 type: String (singleChoice / multiChoice / text / rating / scale)10 options: ["Option A", "Option B", ...] (for choice types)11 isRequired: bool12 order: int13 conditionalNext: Map14 { "0": 5, "1": 3 } // option index → target order1516 survey_responses/{responseId}17 surveyId: String18 userId: String19 responses: Map { questionId: answer }20 completedAt: Timestamp2122PAGE: SurveyPage23 Route Parameter: surveyId24 Backend Query: questions subcollection, orderBy order asc2526PAGE STATE:27 questionList: List<Document> (all questions)28 currentQuestionIndex: int = 029 responses: Map = {}30 questionPath: List<int> = [1] // tracks visited question orders3132WIDGET TREE:33 Column34 ├── LinearPercentIndicator35 │ percent: questionPath.length / estimatedTotalQuestions36 ├── PageView (NeverScrollableScrollPhysics)37 │ └── Per question:38 │ Column39 │ ├── Text (questionText, Headline Small)40 │ ├── Conditional Builder (by question.type):41 │ │ singleChoice → RadioButtonGroup (options)42 │ │ multiChoice → CheckboxGroup (options)43 │ │ text → TextField (multiline)44 │ │ rating → Row of 5 star IconButtons45 │ │ scale → Slider (1-10)46 │ └── SizedBox (16)47 └── Row48 ├── Button ("Back", visible if questionPath.length > 1)49 │ On Tap: pop last from questionPath → animate to previous50 └── Button ("Next" / "Submit")51 On Tap:52 1. Validate required53 2. Save answer to responses Map54 3. Check conditionalNext for selected option55 4. If match → jump to target order question56 5. Else → next sequential question57 6. Append to questionPath58 7. If last → save to survey_responses + navigate to ThankYouCommon mistakes when building a Multi-Step Survey with Conditional Logic in FlutterFlow
Why it's a problem: Progress bar showing currentQuestion divided by totalQuestions regardless of branching
How to avoid: Calculate the estimated remaining questions by following the default path from the current question. Display progress as questionsAnswered divided by estimatedTotal.
Why it's a problem: Not validating required questions before allowing the Next tap
How to avoid: On Next tap, check if the current question isRequired and whether a response exists in the Map. Show a SnackBar error if missing.
Why it's a problem: Storing conditional branching logic only in the Action Flow instead of Firestore
How to avoid: Store conditionalNext rules as a Map field on each question document. The Action Flow reads this map dynamically at runtime.
Best practices
- Store branching rules in Firestore so surveys can be updated without app changes
- Use Conditional Builder to render different input types from a single PageView template
- Show an adaptive progress bar based on the current branch path, not total questions
- Validate required fields before allowing navigation to the next question
- Track the question path in Page State to support a Back button through branches
- Save responses as a Map keyed by questionId for easy analysis
- Test all branching paths with sample data before publishing the survey
Still stuck?
Copy one of these prompts to get a personalized, step-by-step explanation.
I want to build a multi-step survey in FlutterFlow with conditional branching. Questions have different types (single choice, multi choice, text, rating, scale) and a conditionalNext map that routes to different questions based on the selected answer. Give me the Firestore data model, PageView widget tree, and branching navigation logic.
Create a survey page with a progress bar at the top, a question heading in the center, different answer input types below (radio buttons, checkboxes, text field, star rating, slider), and Next and Back buttons at the bottom.
Frequently asked questions
How many branching levels can a survey have?
There is no technical limit on branching depth. Each question can point to any other question by order number. However, keep surveys under 20 questions total for good user experience, even with branching.
Can I add a Back button that works with branching?
Yes. Track the visited question orders in a questionPath list. On Back tap, pop the last entry from the list and animate the PageView to the previous question in the path.
How do I analyze responses from branching surveys?
Each response document contains the full responses Map. Not all users answer the same questions. When analyzing, group by the questions that were actually answered rather than assuming all users saw every question.
Can I make a question conditionally required?
Yes. Add a conditionalRequired field to the question document that specifies under which conditions the question becomes required. Check this field in your validation logic before allowing Next.
How do I handle loops in branching logic?
Avoid creating circular paths where question A routes to B and B routes back to A. If you need repeated sections, use a loop counter in Page State and exit the loop after a set number of iterations.
Can RapidDev help build an advanced survey platform?
Yes. RapidDev can build full survey platforms with complex branching, piping answers into later questions, response analytics dashboards, and export to CSV or Google Sheets.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation