How to validate on unfocus?
woellij opened this issue · 4 comments
I'm trying to validate on unfocus, but calling SingleFieldBloc.validate
does not emit a new state. Also after input change, a state is emitted, saying it is not dirty. Of course autoValidate is deactivated, but that's the whole point (with it on the validation works)
How can i manually call validate
on SingleFieldBloc
s and have the error displayed in the TextFieldBlocBuilder
?
I've been banging my head against this for hours now ...
the implementation of validate
seems to be completely besides the point, what the method-name is conveying ...
You may mind this example:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_form_bloc/flutter_form_bloc.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(),
home: BlocProvider<MyFormBloc>(
create: (_) => MyFormBloc(),
child: const MyHomePage(title: 'Flutter Demo Home Page'),
),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final emailFocusNode = FocusNode();
@override
void initState() {
super.initState();
emailFocusNode.addListener(() {
if (emailFocusNode.hasFocus) {
formBloc.removeEmailValidators();
} else {
formBloc.addEmailValidators();
}
});
}
MyFormBloc get formBloc => context.read<MyFormBloc>();
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
FocusScope.of(context).unfocus();
},
child: Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextFieldBlocBuilder(
obscureText: false,
focusNode: emailFocusNode,
textFieldBloc: formBloc.emailFieldBloc,
suffixButton: SuffixButton.obscureText,
decoration: const InputDecoration(
labelText: 'TextFieldBlocBuilder',
prefixIcon: Icon(Icons.text_fields),
errorStyle: TextStyle(color: Colors.red),
border: OutlineInputBorder(),
),
),
],
),
),
),
);
}
@override
void dispose() {
emailFocusNode.dispose();
super.dispose();
}
}
class MyFormBloc extends FormBloc {
MyFormBloc() {
addFieldBloc(fieldBloc: emailFieldBloc);
}
final emailValidators = [
(text) => 'error here',
];
final emailFieldBloc = TextFieldBloc();
void addEmailValidators() {
emailFieldBloc.updateValidators(emailValidators);
}
void removeEmailValidators() {
emailFieldBloc.updateValidators([]);
}
@override
void submit() {
addEmailValidators();
super.submit();
}
@override
FutureOr<void> onSubmitting() {
throw UnimplementedError();
}
}
Hi @saawhitelife ,
thanks for getting back to me.
I had this on my plate for a while and while trying to implement it i faced a different issue where with the docker built page, the validation stopped working alltogether (maybe something to do with different pub versions)
Because of that i switched over to reactive_forms (https://pub.dev/packages/reactive_forms) which has the notion of only validating "touched" fields by default. Of course without the utilities of form_bloc.
I am also interested in this. Having fields light up in red once the user starts typing is too agressive.
While not the same, as an alternative workaround, you can call field.updateValidators(...)
on the submit button press, adding all your validators, to only validate once the user clicks "submit".
My proposal: #331