formini

在 Flutter 中处理表单不应该如此困难。

请注意,schemani/formini 包仍在开发中。在对实际用例有任何帮助之前,仍有一些问题需要解决。

用法

Formini 不关心你使用什么输入。不过,它提供了开箱即用的 TextEditingController,通过 state.controller 访问。对于 TextField 以外的输入,你可以使用 state.onChangestate.field.value

值不仅限于 Dart 内置类型。如果你想将日期字段存储为 DateTime 并以格式化方式显示值,这是完全可以的。

Login form using formini

import 'package:flutter/material.dart';
import 'package:formini/formini.dart';

class LoginForm extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Formini(
      validator: const LoginFormValidator(),
      initialValues: const {'email': 'foo'},
      onSubmit: _authenticate,
      child: Column(children: [
        ForminiStateBuilder(builder: (context, form) {
          return Column(children: [
            Text('Status: ${form.status}'),
            Text('Values: ${form.values}'),
          ]);
        }),
        ForminiField(
          name: 'email',
          builder: (context, state) => TextField(
            controller: state.controller,
            decoration: InputDecoration(
              labelText: 'Email address',
              errorText: state.field.errorText,
            ),
          ),
        ),
        ForminiField(
          name: 'password',
          builder: (context, state) => TextField(
            controller: state.controller,
            obscureText: true,
            decoration: InputDecoration(
              labelText: 'Password',
              errorText: 
                  state.field.touched ? state.field.error?.toString() : null,
            ),
          ),
        ),
        ForminiStateBuilder(builder: (context, form) {
          return RaisedButton(
            onPressed: form.submit,
            child: Text('Login'),
          );
        }),
      ]),
    );
  }

  Future<bool> _authenticate(Map<String, dynamic> credentials) async {
    // Do what ever you need to do here.
    print(credentials);
    
    return true;
  }
}

验证

在你的验证器类中实现 Validator 接口。

1. 选项 - 手动

import 'package:formini/formini.dart';

class LoginFormValidator implements Validator {
  const LoginFormValidator();

  @override
  Map<String, Exception> validate(Map<String, dynamic> values) {
    final errors = <String, Exception>{};

    if (values['email'] == null || values['email'].isEmpty) {
      errors['email'] = Exception('Email is required');
    } else if (!values['email'].contains('@')) {
      errors['email'] = Exception('Email is invalid');
    }

    if (values['password'] == null || values['password'].isEmpty) {
      errors['password'] = Exception('Password is required');
    }

    return errors;
  }
}

2. 选项 - Schemani(推荐)

使用 formini-schemani 包来使用 schemani 验证值。或者直接将那个简单的文件复制到你的项目中。

import 'package:schemani/schemani.dart';
import 'package:formini-schemani/validator.dart';

const LoginFormValidator = ForminiSchemaniValidator(MapSchema({
  'email': [Required(), Email()],
  'password': [Required()],
}));

API 参考

https://pub.dev/documentation/formini

GitHub

https://github.com/vantageoy/formini