Form & TextFormField(每日Flutter 小部件)
表单 Form
引入 validation_extensions 1.0.1 三方库
使用到了Flutter 中的扩展函数
import 'package:flutter/material.dart'; import 'package:validation_extensions/validation_extensions.dart'; class FormContainerWidget extends StatefulWidget { FormContainerWidget({Key key}) : super(key: key); _FormContainerWidgetState createState() => _FormContainerWidgetState(); } class _FormContainerWidgetState extends State<FormContainerWidget> { final _formKey = GlobalKey<FormState>(); String password; String usernameValidation(String v) => v.isRequired()(); String emailValidation(String v) => [v.isRequired(), v.isEmail()].validate(); String ageValidation(String v) => v.min(18, errorText: "You must be older than 18")(); String passwordValidation(String v) => [ v.isRequired(), v.minLength(8), ].validate(); String confirmPasswordValidation(String v) => [ v.isRequired(), v.minLength(8), v.match(password), ].validate(); validate() { _formKey.currentState.validate(); } resetForm() { _formKey.currentState.reset(); } @override Widget build(BuildContext context) { return Expanded( child: SingleChildScrollView( child: Padding( padding: const EdgeInsets.all(24.0), child: Form( key: _formKey, child: Column( children: <Widget>[ TextFormField( validator: usernameValidation, decoration: InputDecoration( labelText: "Username*", ), ), TextFormField( validator: emailValidation, decoration: InputDecoration( labelText: "Email address*", ), ), TextFormField( validator: ageValidation, decoration: InputDecoration( labelText: "Age", hintText: "Optional age"), ), TextFormField( validator: passwordValidation, obscureText: true, onChanged: (v) => password = v, decoration: InputDecoration( labelText: "Password*", ), ), TextFormField( validator: confirmPasswordValidation, obscureText: true, decoration: InputDecoration( labelText: "Confirm password*", ), ), Padding( padding: const EdgeInsets.all(24.0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: <Widget>[ RaisedButton( color: Colors.lightBlue, onPressed: validate, child: Text("Validate"), ), RaisedButton( color: Colors.redAccent, onPressed: resetForm, child: Text("Reset form"), ), ], ), ), ], ), ), ), ), ); } }
扩展函数如下:
library validationextensions; var emailRegExp = r"[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?"; extension MultiValidations on List<Function> { String validate() { String errorText; for (int i = 0; i < this.length; i++) { errorText = this[i](); if (errorText != null) { break; } } return errorText; } } extension Validations on String { Function isRequired({String errorText}) => () => this.isEmpty || this == null ? errorText ?? "This Field is required" : null; Function isEmail({String errorText}) => () => this == "" ? null : !RegExp(emailRegExp).hasMatch(this) ? errorText ?? "invalid Email address" : null; Function minLength(int min, {String errorText}) => () => this == "" ? null : this.length < min ? errorText ?? "minimum length is $min characters" : null; Function maxLength(int max, {String errorText}) => () => this == "" ? null : this.length > max ? errorText ?? "maximum length is $max characters" : null; Function lengthRange(int min, int max, {String errorText}) => () => this == "" ? null : this.length < min || this.length > max ? errorText ?? "length must be between $min & $max characters" : null; Function match(String stringToMatch, {String errorText}) => () => this == "" ? null : !RegExp("^$stringToMatch\$", caseSensitive: true).hasMatch(this) ? errorText ?? "Values doesn't match" : null; Function matchPattern(String regExp, {String errorText}) => () => this == "" ? null : !RegExp("$regExp").hasMatch(this) ? errorText ?? "Pattern doesn't match" : null; Function isInt({String errorText}) => () => this == "" ? null : int.tryParse(this) == null ? errorText ?? "invalid integer" : null; Function isDouble({String errorText}) => () => this == "" ? null : double.tryParse(this) == null ? errorText ?? "invalid double" : null; Function min(int min, {String errorText}) => () => this == "" ? null : double.tryParse(this) == null || double.parse(this) < min ? errorText ?? "Number must be bigger than $min" : null; Function max(int max, {String errorText}) => () => this == "" ? null : double.tryParse(this) == null || double.parse(this) > max ? errorText ?? "Number must be smaller than $max" : null; Function range(int min, int max, {String errorText}) => () => this == "" ? null : double.tryParse(this) == null && double.parse(this) < min && double.parse(this) > max ? errorText ?? "Number must be between $min & $max" : null; }