From b5c529a2f3e23c3c6a7f319f9561d4958a70b9fe Mon Sep 17 00:00:00 2001 From: "Alexey M. Pereverzev" Date: Sat, 4 Jun 2022 14:30:30 +0300 Subject: [PATCH 1/2] =?UTF-8?q?=D0=94=D0=97=20=D0=BF=D0=BE=2020=20=D1=83?= =?UTF-8?q?=D1=80=D0=BE=D0=BA=D1=83.=20=D0=A1=D1=82=D0=B5=D0=B9=D1=82?= =?UTF-8?q?=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- flutter_base/lib/mobx/form/form_store.dart | 3 +- flutter_base/lib/my_form_bloc/main.dart | 119 ++++++++++++ .../lib/my_form_bloc/my_form_bloc.dart | 181 ++++++++++++++++++ 3 files changed, 301 insertions(+), 2 deletions(-) create mode 100644 flutter_base/lib/my_form_bloc/main.dart create mode 100644 flutter_base/lib/my_form_bloc/my_form_bloc.dart diff --git a/flutter_base/lib/mobx/form/form_store.dart b/flutter_base/lib/mobx/form/form_store.dart index 6f39e91..219b50c 100644 --- a/flutter_base/lib/mobx/form/form_store.dart +++ b/flutter_base/lib/mobx/form/form_store.dart @@ -41,7 +41,7 @@ abstract class _FormStore with Store { @action void validateEmail(String value) { - error.email = isEmail(value) ? 'Not a valid email' : null; + error.email = !isEmail(value) ? 'Not a valid email' : null; } @action @@ -65,7 +65,6 @@ abstract class _FormStore with Store { error.username = null; } - error.username = null; } Future checkValidUsername(String value) async { diff --git a/flutter_base/lib/my_form_bloc/main.dart b/flutter_base/lib/my_form_bloc/main.dart new file mode 100644 index 0000000..24a9d56 --- /dev/null +++ b/flutter_base/lib/my_form_bloc/main.dart @@ -0,0 +1,119 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +import 'my_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( + home: BlocProvider( + create: (context) => MyFormBloc(), + child: const AppForm(), + ), + ); + } +} + +class AppForm extends StatelessWidget { + const AppForm({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + final _bloc = context.read(); + return Scaffold( + appBar: AppBar( + title: const Text('Signup form'), + ), + body: Form( + child: Padding( + padding: const EdgeInsets.all(10), + child: Column( + children: [ + BlocBuilder( + bloc: _bloc, + builder: (context, state) { + return TextField( + onChanged: (value) { + _bloc.add(UsernameChanged(value)); + }, + decoration: InputDecoration( + labelText: 'Username', + hintText: 'Pick a username', + errorText: state.errorUsername, + ), + ); + }, + ), + BlocBuilder( + bloc: _bloc, + builder: (context, state) { + return AnimatedOpacity( + duration: const Duration(milliseconds: 300), + opacity: state.isUsernameCheck ? 1 : 0, + child: const LinearProgressIndicator()); + }, + ), + BlocBuilder( + bloc: _bloc, + builder: (context, state) { + return TextField( + onChanged: (value) { + _bloc.add(EmailChanged(value)); + }, + keyboardType: TextInputType.emailAddress, + decoration: InputDecoration( + labelText: 'Email', + hintText: 'Enter your email address', + errorText: state.errorEmail, + ), + ); + }, + ), + BlocBuilder( + bloc: _bloc, + builder: (context, state) { + return TextField( + onChanged: (value) { + _bloc.add(PasswordChanged(value)); + }, + decoration: InputDecoration( + labelText: 'Password', + hintText: 'Set a password', + errorText: state.errorPassword + ), + ); + }, + ), + BlocBuilder( + bloc: _bloc, + builder: (context, state) { + return ElevatedButton( + onPressed: () { + _bloc.add(FormSubmitted()); + if (state.noErrors) { + ScaffoldMessenger.of(context) + ..hideCurrentSnackBar() + ..showSnackBar( + const SnackBar( + content: Text('Registration Success')), + ); + } + }, + child: const Text('Sign up'), + ); + }, + ), + ], + ), + ), + ), + ); + } +} diff --git a/flutter_base/lib/my_form_bloc/my_form_bloc.dart b/flutter_base/lib/my_form_bloc/my_form_bloc.dart new file mode 100644 index 0000000..cd397ef --- /dev/null +++ b/flutter_base/lib/my_form_bloc/my_form_bloc.dart @@ -0,0 +1,181 @@ +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:validators2/validators.dart'; + +abstract class MyFormEvents {} + +class UsernameChanged extends MyFormEvents { + final String username; + + UsernameChanged(this.username); +} + +class EmailChanged extends MyFormEvents { + final String email; + + EmailChanged(this.email); +} + +class PasswordChanged extends MyFormEvents { + final String password; + + PasswordChanged(this.password); +} + +class FormSubmitted extends MyFormEvents {} + +class MyFormState { + final String username; + final String? errorUsername; + final String email; + final String? errorEmail; + final String password; + final String? errorPassword; + final bool isUsernameCheck; + + MyFormState({ + required this.username, + required this.errorUsername, + required this.email, + required this.errorEmail, + required this.password, + required this.errorPassword, + required this.isUsernameCheck, + }); + + bool get noErrors => + username.isNotEmpty && + errorUsername == null && + email.isNotEmpty && + errorEmail == null && + password.isNotEmpty && + errorPassword == null; +} + +class MyFormBloc extends Bloc { + MyFormBloc() + : super(MyFormState( + username: '', + errorUsername: null, + email: '', + errorEmail: null, + password: '', + errorPassword: null, + isUsernameCheck: false, + )) { + on(_onUsernameChanged); + on(_onEmailChanged); + on(_onPasswordChanged); + on(_onFormSubmitted); + } + + void _onUsernameChanged( + UsernameChanged event, Emitter emit) async { + emit(MyFormState( + username: event.username, + errorUsername: _checkUsername(event.username), + email: state.email, + errorEmail: state.errorEmail, + password: state.password, + errorPassword: state.errorPassword, + isUsernameCheck: state.isUsernameCheck, + )); + + try { + emit(MyFormState( + username: state.username, + errorUsername: state.errorUsername, + email: state.email, + errorEmail: state.errorEmail, + password: state.password, + errorPassword: state.errorPassword, + isUsernameCheck: true, + )); + final _isValid = await _checkValidUsername(event.username); + emit(MyFormState( + username: state.username, + errorUsername: state.errorUsername, + email: state.email, + errorEmail: state.errorEmail, + password: state.password, + errorPassword: state.errorPassword, + isUsernameCheck: false, + )); + if (!_isValid) { + emit(MyFormState( + username: event.username, + errorUsername: 'Username cannot be "admin"', + email: state.email, + errorEmail: state.errorEmail, + password: state.password, + errorPassword: state.errorPassword, + isUsernameCheck: state.isUsernameCheck, + )); + + return; + } + } catch (_) { + emit(MyFormState( + username: state.username, + errorUsername: null, + email: state.email, + errorEmail: state.errorEmail, + password: state.password, + errorPassword: state.errorPassword, + isUsernameCheck: state.isUsernameCheck, + )); + } + } + + void _onEmailChanged(EmailChanged event, Emitter emit) => + emit(MyFormState( + username: state.username, + errorUsername: state.errorUsername, + email: event.email, + errorEmail: _checkEmail(event.email), + password: state.password, + errorPassword: state.errorPassword, + isUsernameCheck: state.isUsernameCheck, + )); + + void _onPasswordChanged(PasswordChanged event, Emitter emit) => + emit(MyFormState( + username: state.username, + errorUsername: state.errorUsername, + email: state.email, + errorEmail: state.errorEmail, + password: event.password, + errorPassword: _checkPassword(event.password), + isUsernameCheck: state.isUsernameCheck, + )); + + void _onFormSubmitted(FormSubmitted event, Emitter emit) { + emit(MyFormState( + username: state.username, + errorUsername: state.username.isEmpty + ? _checkUsername(state.username) + : state.errorUsername, + email: state.email, + errorEmail: _checkEmail(state.email), + password: state.password, + errorPassword: _checkPassword(state.password), + isUsernameCheck: state.isUsernameCheck, + )); + } + + String? _checkUsername(String username) { + return isNull(username) ? 'Field is required' : null; + } + + Future _checkValidUsername(String value) async { + await Future.delayed(const Duration(seconds: 1)); + return value != 'admin'; + } + + String? _checkEmail(String email) { + return !isEmail(email) ? 'Not a valid email' : null; + } + + String? _checkPassword(String password) { + return isNull(password) ? 'Field is required' : null; + } +} From 86f5adf207fe0ca27ce23f0eb48d4ec4b32e4731 Mon Sep 17 00:00:00 2001 From: "Alexey M. Pereverzev" Date: Sat, 4 Jun 2022 15:31:27 +0300 Subject: [PATCH 2/2] =?UTF-8?q?=D0=94=D0=97=20=D0=BF=D0=BE=2020=20=D1=83?= =?UTF-8?q?=D1=80=D0=BE=D0=BA=D1=83.=20=D0=A1=D1=82=D0=B5=D0=B9=D1=82?= =?UTF-8?q?=D1=8B.=20copyWith?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lib/my_form_bloc/my_form_bloc.dart | 63 +++++++++---------- 1 file changed, 28 insertions(+), 35 deletions(-) diff --git a/flutter_base/lib/my_form_bloc/my_form_bloc.dart b/flutter_base/lib/my_form_bloc/my_form_bloc.dart index cd397ef..f25a059 100644 --- a/flutter_base/lib/my_form_bloc/my_form_bloc.dart +++ b/flutter_base/lib/my_form_bloc/my_form_bloc.dart @@ -42,6 +42,26 @@ class MyFormState { required this.isUsernameCheck, }); + MyFormState copyWith({ + String? username, + String? errorUsername, + String? email, + String? errorEmail, + String? password, + String? errorPassword, + bool? isUsernameCheck, + }) { + return MyFormState( + username: username ?? this.username, + errorUsername: errorUsername, + email: email ?? this.email, + errorEmail: errorEmail, + password: password ?? this.password, + errorPassword: errorPassword, + isUsernameCheck: isUsernameCheck ?? this.isUsernameCheck, + ); + } + bool get noErrors => username.isNotEmpty && errorUsername == null && @@ -70,95 +90,68 @@ class MyFormBloc extends Bloc { void _onUsernameChanged( UsernameChanged event, Emitter emit) async { - emit(MyFormState( + emit(state.copyWith( username: event.username, errorUsername: _checkUsername(event.username), - email: state.email, errorEmail: state.errorEmail, - password: state.password, errorPassword: state.errorPassword, - isUsernameCheck: state.isUsernameCheck, )); try { - emit(MyFormState( - username: state.username, + emit(state.copyWith( errorUsername: state.errorUsername, - email: state.email, errorEmail: state.errorEmail, - password: state.password, errorPassword: state.errorPassword, isUsernameCheck: true, )); final _isValid = await _checkValidUsername(event.username); - emit(MyFormState( - username: state.username, + emit(state.copyWith( errorUsername: state.errorUsername, - email: state.email, errorEmail: state.errorEmail, - password: state.password, errorPassword: state.errorPassword, isUsernameCheck: false, )); if (!_isValid) { - emit(MyFormState( + emit(state.copyWith( username: event.username, errorUsername: 'Username cannot be "admin"', - email: state.email, errorEmail: state.errorEmail, - password: state.password, errorPassword: state.errorPassword, - isUsernameCheck: state.isUsernameCheck, )); - return; } } catch (_) { - emit(MyFormState( - username: state.username, + emit(state.copyWith( errorUsername: null, - email: state.email, errorEmail: state.errorEmail, - password: state.password, errorPassword: state.errorPassword, - isUsernameCheck: state.isUsernameCheck, )); } } void _onEmailChanged(EmailChanged event, Emitter emit) => - emit(MyFormState( - username: state.username, + emit(state.copyWith( errorUsername: state.errorUsername, email: event.email, errorEmail: _checkEmail(event.email), - password: state.password, errorPassword: state.errorPassword, - isUsernameCheck: state.isUsernameCheck, )); void _onPasswordChanged(PasswordChanged event, Emitter emit) => - emit(MyFormState( - username: state.username, + emit(state.copyWith( errorUsername: state.errorUsername, - email: state.email, errorEmail: state.errorEmail, password: event.password, errorPassword: _checkPassword(event.password), - isUsernameCheck: state.isUsernameCheck, )); void _onFormSubmitted(FormSubmitted event, Emitter emit) { - emit(MyFormState( - username: state.username, + emit(state.copyWith( errorUsername: state.username.isEmpty ? _checkUsername(state.username) : state.errorUsername, - email: state.email, errorEmail: _checkEmail(state.email), - password: state.password, errorPassword: _checkPassword(state.password), - isUsernameCheck: state.isUsernameCheck, )); }