Form Phoenix 🔥

Advanced Form State Time-Travel & Secure Persistence for Flutter.

Form Phoenix is a powerful, dependency-light form state management engine that gives your Flutter forms "Superpowers". It tracks every change, allowing users to Undo, Redo, and Recover their form data seamlessly, even after a full app restart.

Pub Version License: MIT GitHub stars


✨ Features

  • 🔄 Undo / Redo / Replay: Standard time-travel mechanics for any form field.
  • 🔒 Secure Persistence: Automatically save form drafts to flutter_secure_storage.
  • 🛡️ AES Encryption: Encrypt sensitive form data before storing it on disk.
  • 🔗 Auto-Binding: Bidirectional sync with TextEditingController.
  • ⏱️ Debounced Updates: Intelligent snapshotting to prevent history bloating while typing.
  • 🏢 Multi-Step Support: Perfect for complex wizards and multi-page onboarding flows.
  • 🚀 Zero Global State: No Bloc, No Provider, No Redux required. Just a clean Controller.

📦 Installation

Add this to your pubspec.yaml:

dependencies:
  form_phoenix: ^1.0.0

🚀 Quick Start

1. Initialize the Controller

Create and initialize the controller in your StatefulWidget.

late final FormPhoenixController formController;

@override
void initState() {
  super.initState();
  formController = FormPhoenixController(
    persistKey: 'user_profile_form', // Required for persistence
    syncOnRestart: true,             // Auto-load drafts on restart
    enableDataEncryption: true,     // Encrypt stored data
  );
  
  // Initialize to load persisted data
  formController.init();
}

2. Bind your Fields

For TextFields, use bindTextController to sync automatically.

final nameController = TextEditingController();

@override
void initState() {
  // ...
  formController.bindTextController(
    field: 'full_name',
    controller: nameController,
  );
}

For other inputs (Selectors, Sliders, Checkboxes), use updateField:

Checkbox(
  value: formController.getValue<bool>('agreed') ?? false,
  onChanged: (val) => formController.updateFieldImmediate('agreed', val),
)

3. Implement Undo/Redo

Hook up your UI buttons to the controller's time-travel methods.

ListenableBuilder(
  listenable: formController,
  builder: (context, _) {
    return Row(
      children: [
        IconButton(
          icon: Icon(Icons.undo),
          onPressed: formController.canUndo ? formController.undo : null,
        ),
        IconButton(
          icon: Icon(Icons.redo),
          onPressed: formController.canRedo ? formController.redo : null,
        ),
      ],
    );
  },
)

🛠 Advanced Usage

Persistent Storage & Encryption

If syncOnRestart is enabled, Form Phoenix will save a snapshot of the currentData to Secure Storage on every change. If enableDataEncryption is true, the data is encrypted using AES-256 with a key derived from your persistKey.

Clearing State

To wipe all history and delete the saved draft from the device:

await formController.clearHistory();

Handling Files

You can store file paths in the controller just like strings. Form Phoenix will persist the path, and you can reload the file on restart:

void pickImage() async {
  final image = await picker.pickImage(source: ImageSource.gallery);
  if (image != null) {
    formController.updateFieldImmediate('profile_image', image.path);
  }
}

📄 License

MIT License - see LICENSE for details.

🙏 Support

If you like this package, ⭐ Star it on GitHub!
For issues or feature requests, open an issue on GitHub.

Libraries

form_phoenix