手动设置Flutter验证错误 [英] Manually setting Flutter Validation Error

查看:110
本文介绍了手动设置Flutter验证错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在验证表单并将请求从flutter发送到服务器后端后:我想设置来自服务器的任何潜在错误消息,使其以原始表单显示。最好像验证错误一样。

After validating a form and sending a request from flutter to the server backend: I want to set any potential error message from the server to be displayed in the original form. Preferably exactly like a validation error.

例如:

Widget build(BuildContext context) {
...
  TextFormField(
    onFieldSubmitted: (value) => _signIn(),
    validator: (input) {
      if (input.length < 6)
        return 'Your password is too short';
      return null;
    },
    onSaved: (input) => _password = input,
    decoration: InputDecoration(
      labelText: 'Password',
    ),
    obscureText: true,
  )
...
}

Future<void> _signIn() async {
  final formState = _formKey.currentState;
  if (!formState.validate()) return;
  formState.save();

  try {
    ... // do fancy request stuff
  } catch (e) {
    // this is where I want to set the "validation" error
  }
}


推荐答案

您可以使用 flutter_form_bloc 并使用 addError 方法 TextFieldBloc

You can use flutter_form_bloc and use addError method of TextFieldBloc.

usernameField.addError('That username is taken. Try another.');

请记住,您也可以使用异步验证器。

Keep in mind that you can also use asynchronous validators.

这是一个完整的示例:

dependencies:
  flutter:
    sdk: flutter
  flutter_bloc: ^0.21.0
  form_bloc: ^0.5.0
  flutter_form_bloc: ^0.4.1+1



import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_form_bloc/flutter_form_bloc.dart';
import 'package:form_bloc/form_bloc.dart';

void main() {
  runApp(MaterialApp(home: SignUpForm()));
}

class SignUpFormBloc extends FormBloc<String, String> {
  final usernameField = TextFieldBloc();
  final passwordField =
      TextFieldBloc(validators: [Validators.passwordMin6Chars]);

  @override
  List<FieldBloc> get fieldBlocs => [usernameField, passwordField];

  @override
  Stream<FormBlocState<String, String>> onSubmitting() async* {
    // Form logic...
    try {
      await _signUp(
        throwException: true,
        username: usernameField.value,
        password: passwordField.value,
      );
      yield currentState.toSuccess();
    } catch (e) {
      // When get the error from the backend you can
      // add the error to the field:
      usernameField.addError('That username is taken. Try another.');

      yield currentState
          .toFailure('The error was added to the username field.');
    }
  }

  Future<void> _signUp({
    @required bool throwException,
    @required String username,
    @required String password,
  }) async {
    print(username);
    print(password);
    await Future<void>.delayed(Duration(seconds: 2));
    if (throwException) throw Exception();
  }
}

class SignUpForm extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return BlocProvider<SignUpFormBloc>(
      builder: (context) => SignUpFormBloc(),
      child: Builder(
        builder: (context) {
          final formBloc = BlocProvider.of<SignUpFormBloc>(context);

          return Scaffold(
            appBar: AppBar(title: Text('Sign Up Form')),
            body: FormBlocListener<SignUpFormBloc, String, String>(
              onSubmitting: (context, state) {
                // Show the progress dialog
                showDialog(
                  context: context,
                  barrierDismissible: false,
                  builder: (_) => WillPopScope(
                    onWillPop: () async => false,
                    child: Center(
                      child: Card(
                        child: Container(
                          width: 80,
                          height: 80,
                          padding: EdgeInsets.all(12.0),
                          child: CircularProgressIndicator(),
                        ),
                      ),
                    ),
                  ),
                );
              },
              onSuccess: (context, state) {
                // Hide the progress dialog
                Navigator.of(context).pop();
                // Navigate to success screen
                Navigator.of(context).pushReplacement(
                    MaterialPageRoute(builder: (_) => SuccessScreen()));
              },
              onFailure: (context, state) {
                // Hide the progress dialog
                Navigator.of(context).pop();
                // Show snackbar with the error
                Scaffold.of(context).showSnackBar(
                  SnackBar(
                    content: Text(state.failureResponse),
                    backgroundColor: Colors.red[300],
                  ),
                );
              },
              child: ListView(
                children: <Widget>[
                  TextFieldBlocBuilder(
                    textFieldBloc: formBloc.usernameField,
                    decoration: InputDecoration(labelText: 'Username'),
                  ),
                  TextFieldBlocBuilder(
                    textFieldBloc: formBloc.passwordField,
                    decoration: InputDecoration(labelText: 'Password'),
                  ),
                  Padding(
                    padding: const EdgeInsets.all(8.0),
                    child: RaisedButton(
                      onPressed: formBloc.submit,
                      child: Center(child: Text('SUBMIT')),
                    ),
                  ),
                ],
              ),
            ),
          );
        },
      ),
    );
  }
}

class SuccessScreen extends StatelessWidget {
  const SuccessScreen({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.green[300],
      body: Center(
        child: SingleChildScrollView(
          child: Column(
            children: <Widget>[
              Icon(
                Icons.sentiment_satisfied,
                size: 100,
              ),
              RaisedButton(
                color: Colors.green[100],
                child: Text('Sign out'),
                onPressed: () => Navigator.of(context).pushReplacement(
                    MaterialPageRoute(builder: (_) => SignUpForm())),
              )
            ],
          ),
        ),
      ),
    );
  }
}

这篇关于手动设置Flutter验证错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆