Flutter SurveyJS

A Flutter package for rendering SurveyJS forms natively in Flutter applications. This package provides a complete solution for displaying dynamic surveys with support for all major question types.

Features

Complete SurveyJS Integration - Render SurveyJS JSON definitions in Flutter
Dynamic UI Generation - UI is automatically created from JSON ✅ 19+ Question Types - Text, radio, checkbox, dropdown, rating, matrix, slider, file upload, signature, and more
Custom Question Types - Register your own flutter widgets for custom question types ✅ Nested Panels - Support for grouping questions in panels ✅ JSON Validation - Validates survey JSON structure before initialization ✅ Conditional Logic - Full support for SurveyJS visibility conditions and skip logic
Validation - Built-in validation with error messages
Multi-page Surveys - Navigate through survey pages with progress indicator
Customizable Theme - Customize colors, fonts, and styling
Media Support - File upload, image picker, and signature capture
Cross-platform - Works on iOS, Android, and Web

Supported Question Types

Basic Input

  • text - Single-line text input with various input types (email, number, tel, url)
  • comment - Multi-line text area
  • radiogroup - Single choice selection
  • checkbox - Multiple choice selection
  • dropdown - Dropdown selection
  • boolean - Yes/No toggle buttons
  • rating - Star or numeric rating scale

Advanced

  • matrix - Matrix of radio buttons
  • slider - Slider with customizable range
  • tagbox - Multi-select with chips
  • ranking - Drag-and-drop ranking
  • multipletext - Multiple text inputs in one question

Media & Special

  • file - File upload with camera capture
  • imagepicker - Image selection from gallery or camera
  • signaturepad - Signature drawing
  • html - Display HTML content
  • expression - Display calculated values

Complex

  • matrixdropdown - Matrix with per-cell editor mapping from JSON column config
  • matrixdynamic - Dynamic matrix with add/remove rows
  • paneldynamic - Dynamic panels with template elements

Installation

Add this to your package's pubspec.yaml file:

dependencies:
  surveyjs_flutter:
    path: ../surveyjs_flutter  # Use path dependency for now

Then run:

flutter pub get

Android Setup (Important)

Due to the complex nature of SurveyJS traversing thousands of UI Observables, the default flutter_js Android engine (QuickJS) is prone to locking the UI Thread and causing ANR crashes on heavy forms. This package forces JavaScriptCore (a JIT accelerated C++ engine) on Android to achieve identical performance to iOS.

To enable this engine bypass safely, you must link the JavaScriptCore binary inside your Android project:

  1. Add jitpack to your project-level android/build.gradle (or settings.gradle):
allprojects {
    repositories {
        google()
        mavenCentral()
        maven { url "https://jitpack.io" }
    }
}
  1. Add the native binary dependency to your app-level android/app/build.gradle:
dependencies {
    implementation "com.github.fast-development.android-js-runtimes:fastdev-jsruntimes-jsc:0.3.4"
}

Usage

Basic Example

import 'package:flutter/material.dart';
import 'package:surveyjs_flutter/surveyjs_flutter.dart';

class MySurveyPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return SurveyScreen(
      config: SurveyConfig(
        surveyJson: {
          "title": "Customer Satisfaction Survey",
          "pages": [
            {
              "elements": [
                {
                  "type": "rating",
                  "name": "satisfaction",
                  "title": "How satisfied are you with our service?",
                  "isRequired": true,
                  "rateMin": 1,
                  "rateMax": 5,
                },
                {
                  "type": "comment",
                  "name": "feedback",
                  "title": "Additional feedback",
                },
              ]
            }
          ]
        },
        onComplete: (result) {
          print('Survey completed!');
          print('Results: ${result.data}');
        },
        onValueChanged: (questionName, value) {
          print('$questionName changed to: $value');
        },
      ),
    );
  }
}

With Custom Theme

SurveyScreen(
  config: SurveyConfig(
    surveyJson: mySurveyJson,
    theme: SurveyTheme(
      primaryColor: Colors.blue,
      errorColor: Colors.red,
      questionTitleStyle: TextStyle(
        fontSize: 18,
        fontWeight: FontWeight.bold,
      ),
    ),
    onComplete: (result) {
      // Handle completion
    },
  ),
)

Accessing Survey Results

onComplete: (SurveyResult result) {
  // Get all data
  final allData = result.data;
  
  // Get specific answer
  final satisfaction = result.getValue('satisfaction');
  
  // Check if question was answered
  if (result.hasAnswer('feedback')) {
    print('User provided feedback');
  }
  
  // Get timestamp
  print('Completed at: ${result.timestamp}');
}

Advanced Usage

Custom Question Types

You can register your own Flutter widgets for custom question types defined in your JSON.

// 1. Define your custom widget
class ColorPickerWidget extends StatelessWidget {
  final Map<String, dynamic> question;
  final ValueChanged<dynamic> onChanged;
  
  const ColorPickerWidget({required this.question, required this.onChanged});
  
  @override
  Widget build(BuildContext context) {
    // implementing custom color picker...
    return Container();
  }
}

// 2. Register it globally
QuestionFactory.register('colorpicker', (context, question, onChanged) {
  return ColorPickerWidget(question: question, onChanged: onChanged);
});

// 3. Or register strictly for one survey
SurveyScreen(
  config: SurveyConfig(
    surveyJson: mySurveyJson,
    customBuilders: {
      'colorpicker': (context, question, onChanged) => ColorPickerWidget(...)
    }
  )
)

JSON Validation

By default, the package specifically validates your JSON structure before initialization to catch errors early.

SurveyScreen(
  config: SurveyConfig(
    surveyJson: mySurveyJson,
    // Disable validation if needed
    validateJson: false,
    // Handle validation errors manually
    onValidationError: (errors) {
      print('Validation failed: $errors');
    }
  )
)

Example App

Check out the /example directory for a complete example app showcasing:

  • Customer Satisfaction Survey
  • Job Application Form
  • Product Feedback
  • Health Assessment
  • Event Registration
  • Media Input Survey (file upload, image picker, signature)
  • Advanced Question Types
  • Slider Showcase

Run the example:

cd example
flutter run

Requirements

  • Flutter SDK: >=3.0.0
  • Dart SDK: >=3.0.0

Dependencies

  • flutter_js - JavaScript runtime for SurveyJS engine
  • file_picker - File selection
  • image_picker - Image selection and camera capture
  • signature - Signature drawing
  • mime - MIME type detection

Limitations

  • Some advanced SurveyJS features inside complex question types may be partially implemented
  • Some advanced SurveyJS features may not be fully supported
  • JavaScript execution may have performance implications on large surveys

Contributing

Contributions are welcome! Please feel free to submit issues or pull requests.

License

This package is licensed under the MIT License.

Additional Resources

Libraries

surveyjs_flutter
Flutter SurveyJS - A Flutter package for rendering SurveyJS forms