injectTextEditing static method
- String text = '',
- TextSelection selection = const TextSelection.collapsed(offset: -1),
- TextRange composing = TextRange.empty,
- List<
String? Function(String? text)> ? validators, - bool? validateOnTyping,
- bool? validateOnLoseFocus,
- void onTextEditing(
- InjectedTextEditing textEditing
- bool? isReadOnly,
- bool? isEnabled,
- bool autoDispose = true,
Inject a TextEditingController
This injected state abstracts the best practices to come out with a simple, clean, and testable approach deal with TextField and form validation.
The approach consists of the following steps:
final email = RM.injectTextEditing():
- Instantiate an InjectedTextEditing object using RM.injectTextEditing
- Link the injected state to a TextField (No need to TextFormField even
inside a OnFormBuilder).
TextField( controller: email.controller, focusNode: email.focusNode, //It is auto disposed of. decoration: InputDecoration( errorText: email.error, //To display the error message. ), onSubmitted: (_) { //Focus on the password TextField after submission password.focusNode.requestFocus(); }, ),
See also :
- InjectedFormField for other type of inputs rather the text,
- InjectedForm and OnFormBuilder to work with form.
Parameters:
text
: Optional String. Defaults to empty string.
The initial text the linked TextField displays.
selection
: Optional TextSelection. Defaults to empty TextSelection.collapsed(offset: -1)
.
The initial text selection the linked TextField starts with.
composing
: Optional TextRange. Defaults to empty TextRange.empty
The initial range of text the linked TextField starts with.
validators
: Optional List of callbacks.
Set of validation rules the field should pass.
Validators expose the text that the user entered.
If any of the validation callbacks return a non-empty string, the filed is considered non valid. For the field to be valid all validators must return null.
example:
final _email = RM.injectTextEditing(
validators: [
(value) {
//Frontend validation
if (!Validators.isValidEmail(value)) {
return 'Enter a valid email';
}
},
]
);
The validations performed here are frontend validation. To do backend validation you must use InjectedForm.
validateOnTyping
: Optional bool.
Whether to validate the input while the user is typing.
The default value depends on whether the linked TextField is inside or outside OnFormBuilder:
- If outside: it default to true if
validateOnLoseFocus
is false. - If inside: it defaults to false if InjectedForm.autovalidateMode is AutovalidateMode.disabled, otherwise it defaults to true.
If validateOnTyping
is set to false, the text is not validate on typing.
The text can be validate manually by invoking InjectedTextEditing.validate.
validateOnLoseFocus
: Optional bool.
Whether to validate the input just after the user finishes typing and the field loses focus.
It defaults to true if the linked TextField is inside OnFormBuilder and defaults to false if it is outside.
Once the TextField loses focus and if it fails to validate, the field will auto-validate on typing the next time the user starts typing.
For validateOnLoseFocus
to work you have to set the TextField's FocusNode
to use InjectedTextEditing.focusNode
Example:
final email = RM.injectTextEditing():
// In the widget tree
TextField(
controller: email.controller,
focusNode: email.focusNode, //It is auto disposed of.
),
isReadOnly
: Optional bool. Defaults to false.
If true the TextField is clickable and selectable but not editable. Later on, you can set it using InjectedTextEditing.isReadOnly
All input fields are set to be read-only if they are inside a OnFormBuilder and the form is waiting for submission to resolve.
isEnabled
: Optional bool. Defaults to true.
If false the TextField is disabled.
Later on, you can set it using InjectedTextEditing.isEnable
.
You can enable or disable all input fields inside OnFormBuilder using
InjectedForm.isEnabled
setter.
For isEnabled
to work you have to set the TextField's enable property
to use InjectedTextEditing.isEnabled
Example:
final email = RM.injectTextEditing():
// In the widget tree
TextField(
controller: email.controller,
enabled: email.isEnabled,
),
onTextEditing
: Optional callback.
Callback for side effects. It is fired whenever the input text or selection changes
isReadOnly
: Optional bool. Defaults to false.
If true the input is clickable and selectable but not editable. Later on, you can set it using InjectedTextEditing.isReadOnly.
See OnFormBuilder.isReadOnlyRM to set a group of input fields to read only.
isEnabled
: Optional bool. Defaults to true.
If false the OnFormFieldBuilder is disabled. Later on, you can set it using InjectedTextEditing.isEnabled.
See OnFormBuilder.isReadOnlyRM to disable a group of input fields.
autoDisposeWhenNotUsed
: Optional bool (Default true)
Whether to auto dispose the injected model when no longer used (listened to).
It is important to note that:
- A state never listened to for rebuild, never auto dispose even after it is mutated.
- By default, all states consumed in the widget tree will auto dispose.
- It is recommended to manually dispose state that are not auto disposed
using
InjectedBaseState.dispose
. You can dispose all states of the app using RM.disposeAll. - A state will auto dispose if all states it depends on are disposed of.
- Non disposed state may lead to unexpected behavior.
- To debug when state is initialized and disposed of use
debugPrintWhenNotifiedPreMessage
parameter (See below)
Implementation
static InjectedTextEditing injectTextEditing({
String text = '',
TextSelection selection = const TextSelection.collapsed(offset: -1),
TextRange composing = TextRange.empty,
List<String? Function(String? text)>? validators,
bool? validateOnTyping,
bool? validateOnLoseFocus,
void Function(InjectedTextEditing textEditing)? onTextEditing,
bool? isReadOnly,
bool? isEnabled,
bool autoDispose = true,
}) {
return InjectedTextEditingImp(
text: text,
selection: selection,
composing: composing,
validator: validators,
validateOnTyping: validateOnTyping,
validateOnLoseFocus: validateOnLoseFocus,
autoDispose: autoDispose,
onTextEditing: onTextEditing,
isReadOnly: isReadOnly,
isEnabled: isEnabled,
);
}