Skip to content
This repository has been archived by the owner. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions flutter_base/lib/mobx/form/form_store.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -65,7 +65,6 @@ abstract class _FormStore with Store {
error.username = null;
}

error.username = null;
}

Future<bool> checkValidUsername(String value) async {
Expand Down
119 changes: 119 additions & 0 deletions flutter_base/lib/my_form_bloc/main.dart
Original file line number Diff line number Diff line change
@@ -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<MyFormBloc>(
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<MyFormBloc>();
return Scaffold(
appBar: AppBar(
title: const Text('Signup form'),
),
body: Form(
child: Padding(
padding: const EdgeInsets.all(10),
child: Column(
children: [
BlocBuilder<MyFormBloc, MyFormState>(
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<MyFormBloc, MyFormState>(
bloc: _bloc,
builder: (context, state) {
return AnimatedOpacity(
duration: const Duration(milliseconds: 300),
opacity: state.isUsernameCheck ? 1 : 0,
child: const LinearProgressIndicator());
},
),
BlocBuilder<MyFormBloc, MyFormState>(
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<MyFormBloc, MyFormState>(
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<MyFormBloc, MyFormState>(
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'),
);
},
),
],
),
),
),
);
}
}
174 changes: 174 additions & 0 deletions flutter_base/lib/my_form_bloc/my_form_bloc.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
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,
});

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 &&
email.isNotEmpty &&
errorEmail == null &&
password.isNotEmpty &&
errorPassword == null;
}

class MyFormBloc extends Bloc<MyFormEvents, MyFormState> {
MyFormBloc()
: super(MyFormState(
username: '',
errorUsername: null,
email: '',
errorEmail: null,
password: '',
errorPassword: null,
isUsernameCheck: false,
)) {
on<UsernameChanged>(_onUsernameChanged);
on<EmailChanged>(_onEmailChanged);
on<PasswordChanged>(_onPasswordChanged);
on<FormSubmitted>(_onFormSubmitted);
}

void _onUsernameChanged(
UsernameChanged event, Emitter<MyFormState> emit) async {
emit(state.copyWith(
username: event.username,
errorUsername: _checkUsername(event.username),
errorEmail: state.errorEmail,
errorPassword: state.errorPassword,
));

try {
emit(state.copyWith(
errorUsername: state.errorUsername,
errorEmail: state.errorEmail,
errorPassword: state.errorPassword,
isUsernameCheck: true,
));
final _isValid = await _checkValidUsername(event.username);
emit(state.copyWith(
errorUsername: state.errorUsername,
errorEmail: state.errorEmail,
errorPassword: state.errorPassword,
isUsernameCheck: false,
));
if (!_isValid) {
emit(state.copyWith(
username: event.username,
errorUsername: 'Username cannot be "admin"',
errorEmail: state.errorEmail,
errorPassword: state.errorPassword,
));
return;
}
} catch (_) {
emit(state.copyWith(
errorUsername: null,
errorEmail: state.errorEmail,
errorPassword: state.errorPassword,
));
}
}

void _onEmailChanged(EmailChanged event, Emitter<MyFormState> emit) =>
emit(state.copyWith(
errorUsername: state.errorUsername,
email: event.email,
errorEmail: _checkEmail(event.email),
errorPassword: state.errorPassword,
));

void _onPasswordChanged(PasswordChanged event, Emitter<MyFormState> emit) =>
emit(state.copyWith(
errorUsername: state.errorUsername,
errorEmail: state.errorEmail,
password: event.password,
errorPassword: _checkPassword(event.password),
));

void _onFormSubmitted(FormSubmitted event, Emitter<MyFormState> emit) {
emit(state.copyWith(
errorUsername: state.username.isEmpty
? _checkUsername(state.username)
: state.errorUsername,
errorEmail: _checkEmail(state.email),
errorPassword: _checkPassword(state.password),
));
}

String? _checkUsername(String username) {
return isNull(username) ? 'Field is required' : null;
}

Future<bool> _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;
}
}