Controls
Abstractions over controllers that define where widget state lives.
Controls are abstractions over controllers, e.g. TextEditingController, that define where state lives.
Instead of passing controllers to Forui widgets, you pass controls (that optionally wrap controllers).
There are 2 types of controls.
Lifted
You externally manage the state. The widget is "dumb" and just reflects the passed-in values. This is similar to React's controlled components.
1 FPopover(2 control: .lifted(3 shown: _shown,4 onChange: (shown) => setState(() => _shown = shown),5 ),6 child: const Placeholder(),7 popoverBuilder: (_, _) => const Placeholder(),8 );9Managed
The widget internally manages its own state, either through an internal controller configured using the passed-in initial values, or through a passed-in external controller. In the latter case, you are responsible for managing the controller's lifecycle.
1// FPopover manages its own state using an internal controller.2FPopover(3 control: const .managed(initial: false, onChange: print),4 child: const Placeholder(),5 popoverBuilder: (_, _) => const Placeholder(),6);78// FPopover manages its own state using an external controller.9FPopover(10 control: .managed(controller: _externalController),11 child: const Placeholder(),12 popoverBuilder: (_, _) => const Placeholder(),13);14When to Use Which?
TL;DR: Start with "Managed with internal controller" for simplicity and switch as needed.
Common scenarios
-
Lifted:
- Syncing state between your state management solution, e.g. Riverpod, and the widget.
- Reacting to every state change and potentially modifying the state.
-
Managed with external controller:
- Using a lifecycle management solution, e.g. Flutter Hooks.
- Programmatically triggering actions, e.g. showing a popover.
-
Managed with internal controller:
- Prototyping.
- Simply setting an initial value.
- Passively observing state changes.