Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/felangel/flow_builder

Flutter Flows made easy! A Flutter package which simplifies navigation flows with a flexible, declarative API.
https://github.com/felangel/flow_builder

dart flutter flutter-package navigation navigator router routing

Last synced: 22 days ago
JSON representation

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

Awesome Lists containing this project

README

        


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.

```dart
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.

```dart
FlowBuilder(
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().update`.

```dart
class NameForm extends StatefulWidget {
@override
_NameFormState createState() => _NameFormState();
}

class _NameFormState extends State {
var _name = '';

void _continuePressed() {
context.flow().update((profile) => profile.copyWith(name: _name));
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Name')),
body: Center(
child: Column(
children: [
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().complete`.

```dart
class AgeForm extends StatefulWidget {
@override
_AgeFormState createState() => _AgeFormState();
}

class _AgeFormState extends State {
int? _age;

void _continuePressed() {
context
.flow()
.complete((profile) => profile.copyWith(age: _age));
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Age')),
body: Center(
child: Column(
children: [
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.

```dart
class MyFlow extends StatefulWidget {
@override
State createState() => _MyFlowState();
}

class _MyFlowState extends State {
late FlowController _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();
}
}
```