首页 > 解决方案 > 颤振表单订阅验证器中的任何验证更改以禁用提交按钮

问题描述

如何订阅颤振表单中的任何验证更改?

当任何验证器返回“必需”字符串时,我想禁用表单提交按钮。

_formKey.currentState.validate()我可以通过使用每个TextField.onChanged函数中的调用更新我自己的状态对象来手动同步所有这些。然后在没有人更改 TextFields 中的任何内容时将提交设置为默认禁用。

那是我必须走的路吗?

以角度形式,我可以订阅验证更改:-P

标签: flutter

解决方案


您可以使用flutter_form_bloc,在这个包中每个表单都是一个bloc,因此您可以订阅任何表单更改,当然如果所有字段都有效。

要在任何字段出现验证错误时禁用按钮,您必须使用 aBlocBuilderFormBloc,然后简单地使用该isValid属性。

BlocBuilder<SimpleLoginFormBloc, FormBlocState>(
  builder: (context, state) {
    return Padding(
      padding: const EdgeInsets.all(8.0),
        child: RaisedButton(
          onPressed: state.isValid ? formBloc.submit : null,
          child: Center(child: Text('LOGIN')),
        ),
    );
  },
)

flutter_form_bloc具有其他有用的功能,例如通过轻松响应表单状态来导航的侦听器、异步验证等。阅读文档并查看示例。

这是禁用提交按钮的最小示例:

dependencies:
  form_bloc: ^0.7.0
  flutter_form_bloc: ^0.6.0
  flutter_bloc: ^3.2.0
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(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: SimpleLoginForm(),
    );
  }
}

class SimpleLoginFormBloc extends FormBloc<String, String> {
  final emailField = TextFieldBloc(
    validators: [FieldBlocValidators.email],
  );
  final passwordField = TextFieldBloc(
    validators: [FieldBlocValidators.requiredTextFieldBloc],
  );

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

  @override
  Stream<FormBlocState<String, String>> onSubmitting() async* {
    // Login logic...

    // Get the fields values:
    print(emailField.value);
    print(passwordField.value);

    await Future<void>.delayed(Duration(seconds: 2));
    yield state.toSuccess();
  }
}

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

          return Scaffold(
            appBar: AppBar(title: Text('Simple login')),
            body: ListView(
              physics: ClampingScrollPhysics(),
              children: <Widget>[
                TextFieldBlocBuilder(
                  textFieldBloc: formBloc.emailField,
                  keyboardType: TextInputType.emailAddress,
                  decoration: InputDecoration(
                    labelText: 'Email',
                    prefixIcon: Icon(Icons.email),
                  ),
                ),
                TextFieldBlocBuilder(
                  textFieldBloc: formBloc.passwordField,
                  suffixButton: SuffixButton.obscureText,
                  decoration: InputDecoration(
                    labelText: 'Password',
                    prefixIcon: Icon(Icons.lock),
                  ),
                ),
                BlocBuilder<SimpleLoginFormBloc, FormBlocState>(
                  builder: (context, state) {
                    return Padding(
                      padding: const EdgeInsets.all(8.0),
                      child: RaisedButton(
                        onPressed: state.isValid ? formBloc.submit : null,
                        child: Center(child: Text('LOGIN')),
                      ),
                    );
                  },
                )
              ],
            ),
          );
        },
      ),
    );
  }
}

推荐阅读