Skip to content

felangel/flow_builder

Repository files navigation

Flow Builder

Flutter Flows made easy!

build coverage pub package

Usage

Define a Flow State

The flow state will be the state which drives the flow. Each time this state changes, a new navigation stack will be generated based on the new flow state.

class Profile { const Profile({this.name, this.age, this.weight}); final String? name; final int? age; final int? weight; Profile copyWith({String? name, int? age, int? weight}) { return Profile( name: name ?? this.name, age: age ?? this.age, weight: weight ?? this.weight, ); } }

Create a FlowBuilder

FlowBuilder is a widget which builds a navigation stack in response to changes in the flow state. onGeneratePages will be invoked for each state change and must return the new navigation stack as a list of pages.

FlowBuilder<Profile>( state: const Profile(), onGeneratePages: (profile, pages) { return [ MaterialPage(child: NameForm()), if (profile.name != null) MaterialPage(child: AgeForm()), ]; }, );

Update the Flow State

The state of the flow can be updated via context.flow<T>().update.

class NameForm extends StatefulWidget { @override _NameFormState createState() => _NameFormState(); } class _NameFormState extends State<NameForm> { var _name = ''; void _continuePressed() { context.flow<Profile>().update((profile) => profile.copyWith(name: _name)); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('Name')), body: Center( child: Column( children: <Widget>[ TextField( onChanged: (value) => setState(() => _name = value), decoration: InputDecoration( labelText: 'Name', hintText: 'John Doe', ), ), RaisedButton( child: const Text('Continue'), onPressed: _name.isNotEmpty ? _continuePressed : null, ) ], ), ), ); } }

Complete the Flow

The flow can be completed via context.flow<T>().complete.

class AgeForm extends StatefulWidget { @override _AgeFormState createState() => _AgeFormState(); } class _AgeFormState extends State<AgeForm> { int? _age; void _continuePressed() { context .flow<Profile>() .complete((profile) => profile.copyWith(age: _age)); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('Age')), body: Center( child: Column( children: <Widget>[ TextField( onChanged: (value) => setState(() => _age = int.parse(value)), decoration: InputDecoration( labelText: 'Age', hintText: '42', ), keyboardType: TextInputType.number, ), RaisedButton( child: const Text('Continue'), onPressed: _age != null ? _continuePressed : null, ) ], ), ), ); } }

FlowController

A FlowBuilder can also be created with a custom FlowController in cases where the flow can be manipulated outside of the sub-tree.

class MyFlow extends StatefulWidget { @override State<MyFlow> createState() => _MyFlowState(); } class _MyFlowState extends State<MyFlow> { late FlowController<Profile> _controller; @override void initState() { super.initState(); _controller = FlowController(const Profile()); } @override Widget build(BuildContext context) { return FlowBuilder( controller: _controller, onGeneratePages: ..., ); } @override dispose() { _controller.dispose(); super.dispose(); } }

About

Flutter Flows made easy! A Flutter package which simplifies navigation flows with a flexible, declarative API.

Topics

Resources

License

Stars

Watchers

Forks

Sponsor this project

 

Contributors