# How to Create a Custom Survey Widget for Your FlutterFlow App

- Tool: FlutterFlow
- Difficulty: Beginner
- Time required: 25-30 min
- Compatibility: FlutterFlow Free+
- Last updated: March 2026

## TL;DR

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.

## Before you start

- 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

### 1. 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.

### 2. 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.

### 3. 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.

### 4. 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.

### 5. 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 code example

File: `FlutterFlow Survey Setup`

```text
FIRESTORE DATA MODEL:
  surveys/{surveyId}
    title: String
    description: String
    └── questions/{questionId}
          questionText: String
          questionType: "text" | "radio" | "checkbox" | "rating" | "slider"
          options: ["Option A", "Option B", "Option C"] (radio/checkbox only)
          isRequired: Boolean
          order: int
          placeholder: String (text only)

PAGE STATE:
  currentIndex: int = 0
  responses: JSON Map = {}

WIDGET TREE:
  Column
    ├── LinearPercentIndicator (percent: currentIndex / total)
    ├── Expanded
    │     └── PageView (horizontal, NeverScrollableScrollPhysics)
    │           └── Per question:
    │                 Column
    │                   ├── Text (questionText, Headline Small)
    │                   ├── SizedBox (20)
    │                   └── Conditional Builder (questionType)
    │                         ├── "text" → TextField (maxLines: 3, placeholder)
    │                         ├── "radio" → RadioButtonGroup (options)
    │                         ├── "checkbox" → CheckboxGroup (options)
    │                         ├── "rating" → Row of 5 Star Icons
    │                         └── "slider" → Slider (min 1, max 10)
    └── Button ("Next" / "Submit")
          On Tap:
            1. If isRequired && !responses.has(questionId) → Show Error Snackbar
            2. Else if not last → Animate Next Page + increment currentIndex
            3. Else → Create Document survey_responses → Thank You

SURVEY RESPONSES DOCUMENT:
  surveyId: String
  userId: String
  responses: { "questionId1": "answer", "questionId2": 4, ... }
  submittedAt: Timestamp
```

## Common mistakes

- **Not validating required questions before allowing navigation to the next question** — Users skip required fields and submit incomplete surveys, producing useless data. You cannot retroactively ask them to fill in missing responses. Fix: Check the isRequired flag on each question. Block the Next button and show an error if a required question has no response.
- **Using App State instead of Page State for survey responses** — App State persists to disk. If the user abandons a survey and returns, their old partial responses pre-fill, potentially corrupting a new attempt. Fix: Use Page State for in-progress survey data so responses reset when the user leaves the page.
- **Loading all question responses into a flat List instead of a keyed Map** — A flat List breaks if questions are reordered or removed. Question IDs as keys keep responses stable regardless of ordering. Fix: 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

## 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.

---

Source: https://www.rapidevelopers.com/flutterflow-tutorials/how-to-create-a-custom-survey-widget-for-your-flutterflow-app
© RapidDev — https://www.rapidevelopers.com/flutterflow-tutorials/how-to-create-a-custom-survey-widget-for-your-flutterflow-app
