这是我的更改密码屏幕。我正在使用flutter_bloc来实现mvvc模式。此页面可与bloc配合使用。但是我要达到的目的是在提交表单时验证表单。当我刚起步时,我不知道该怎么做。
更改密码事件
abstract class ChangePasswordEvent extends Equatable {
const ChangePasswordEvent();
}
class SubmitButtonPressed extends ChangePasswordEvent {
final String oldPassword;
final String newPassword;
const SubmitButtonPressed({@required this.oldPassword, this.newPassword});
@override
List<Object> get props => [oldPassword, newPassword];
}
更改密码状态
abstract class ChangePasswordState extends Equatable {
const ChangePasswordState();
@override
List<Object> get props => [];
}
class ChangePasswordInitial extends ChangePasswordState {}
class ChangePasswordLoading extends ChangePasswordState {}
class ChangePasswordSuccess extends ChangePasswordState {}
class ChangePasswordFailure extends ChangePasswordState {
final String error;
const ChangePasswordFailure({@required this.error});
@override
List<Object> get props => [error];
@override
String toString() => 'ChangePasswordFailure { error: $error }';
}
更改密码组
class ChangePasswordBloc
extends Bloc<ChangePasswordEvent, ChangePasswordState> {
final UserRepository userRepository;
ChangePasswordBloc({
@required this.userRepository,
}) : assert(userRepository != null);
@override
ChangePasswordState get initialState => ChangePasswordInitial();
@override
Stream<ChangePasswordState> mapEventToState(
ChangePasswordEvent event) async* {
if (event is SubmitButtonPressed) {
yield ChangePasswordLoading();
try {
final bool isPasswordChanged = await userRepository.changePassword(
event.oldPassword,
event.newPassword,
);
if (isPasswordChanged) {
yield ChangePasswordSuccess();
}
} catch (error) {
yield ChangePasswordFailure(error: error);
}
}
}
}
更改密码页面
class ChangePasswordPage extends StatelessWidget {
final UserRepository userRepository;
ChangePasswordPage({Key key, @required this.userRepository})
: assert(userRepository != null),
super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Change Password'),
),
body: Padding(
padding: const EdgeInsets.all(20.0),
child: BlocProvider(
create: (context) {
return ChangePasswordBloc(
userRepository: userRepository,
);
},
child: ChangePasswordForm(),
),
),
);
}
}
更改密码表格
class ChangePasswordForm extends StatefulWidget {
@override
_ChangePasswordFormState createState() => _ChangePasswordFormState();
}
class _ChangePasswordFormState extends State<ChangePasswordForm> {
final userRepository = UserRepository();
final _formKey = GlobalKey<FormState>();
final _oldPassController = TextEditingController();
final _newPassController = TextEditingController();
final _confirmPassController = TextEditingController();
@override
Widget build(BuildContext context) {
_onSubmitButtonPressed() {
BlocProvider.of<ChangePasswordBloc>(context).add(
SubmitButtonPressed(
oldPassword: _oldPassController.text,
newPassword: _newPassController.text,
),
);
}
return BlocListener<ChangePasswordBloc, ChangePasswordState>(
listener: (context, state) {
if (state is ChangePasswordFailure) {
Scaffold.of(context).showSnackBar(
SnackBar(
content: Text('${state.error}'),
backgroundColor: Colors.red,
),
);
}
if (state is ChangePasswordSuccess) {
Scaffold.of(context).showSnackBar(
SnackBar(
content: Text('Password Changed Successfully'),
backgroundColor: Colors.green,
),
);
}
},
child: BlocBuilder<ChangePasswordBloc, ChangePasswordState>(
builder: (context, state) {
return Form(
key: _formKey,
child: Column(
children: [
TextFormField(
decoration: InputDecoration(labelText: 'Old Password'),
controller: _oldPassController,
),
SizedBox(height: 20.0),
TextFormField(
decoration: InputDecoration(labelText: 'New Password'),
controller: _newPassController,
obscureText: true,
),
SizedBox(height: 20.0),
TextFormField(
decoration: InputDecoration(labelText: 'Confirm Password'),
controller: _confirmPassController,
obscureText: true,
validator: (value) {
final String _newPassword = _newPassController.text;
if (_newPassword != value) {
return "Password Mismatch";
}
return null;
},
),
SizedBox(height: 20.0),
RaisedButton(
onPressed: () {
if (state is! ChangePasswordLoading) {
final form = _formKey.currentState;
if (form.validate()) {
return _onSubmitButtonPressed();
}
return null;
}
},
child: Text('Submit'),
),
],
),
);
},
),
);
}
}
答案 0 :(得分:2)
您可以在Form Validation
上查看其示例。该示例验证电子邮件和密码格式,您应该相应地对其进行更改。您的状态应类似于:
class MyFormState extends Equatable {
final String email;
final bool isEmailValid;
final String password;
final bool isPasswordValid;
final bool formSubmittedSuccessfully;
bool get isFormValid => isEmailValid && isPasswordValid;
//....
}
要验证的BLoC:
class MyFormBloc extends Bloc<MyFormEvent, MyFormState> {
final RegExp _emailRegExp = RegExp(
r'^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$',
);
final RegExp _passwordRegExp = RegExp(
r'^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{8,}$',
);
@override
MyFormState get initialState => MyFormState.initial();
@override
void onTransition(Transition<MyFormEvent, MyFormState> transition) {
print(transition);
}
@override
Stream<MyFormState> mapEventToState(
MyFormEvent event,
) async* {
if (event is EmailChanged) {
yield state.copyWith(
email: event.email,
isEmailValid: _isEmailValid(event.email),
);
}
if (event is PasswordChanged) {
yield state.copyWith(
password: event.password,
isPasswordValid: _isPasswordValid(event.password),
);
}
if (event is FormSubmitted) {
yield state.copyWith(formSubmittedSuccessfully: true);
}
if (event is FormReset) {
yield MyFormState.initial();
}
}
bool _isEmailValid(String email) {
return _emailRegExp.hasMatch(email);
}
bool _isPasswordValid(String password) {
return _passwordRegExp.hasMatch(password);
}
}
以及Form构建方法:
@override
Widget build(BuildContext context) {
return BlocBuilder<MyFormBloc, MyFormState>(
builder: (context, state) {
if (state.formSubmittedSuccessfully) {
return SuccessDialog(onDismissed: () {
_emailController.clear();
_passwordController.clear();
_myFormBloc.add(FormReset());
});
}
return Form(
child: Column(
children: <Widget>[
TextFormField(
controller: _emailController,
decoration: InputDecoration(
icon: Icon(Icons.email),
labelText: 'Email',
),
keyboardType: TextInputType.emailAddress,
autovalidate: true,
validator: (_) {
return state.isEmailValid ? null : 'Invalid Email';
},
),
TextFormField(
controller: _passwordController,
decoration: InputDecoration(
icon: Icon(Icons.lock),
labelText: 'Password',
),
obscureText: true,
autovalidate: true,
validator: (_) {
return state.isPasswordValid ? null : 'Invalid Password';
},
),
RaisedButton(
onPressed: state.isFormValid ? _onSubmitPressed : null,
child: Text('Submit'),
),
],
),
);
},
);
}
答案 1 :(得分:0)
我认为最好不要将flutter_bloc软件包用于验证目的,因为它将导致所有控件的重建。而是使用原始对象(如Stream和Provider),如此处所述。 https://www.youtube.com/watch?v=JqWK4oitJFs
附加链接:https://medium.com/swlh/how-to-create-a-simple-login-form-in-flutter-using-bloc-pattern-b55ad52a2a10