高级表单
AdvancedForm 类为 Jinja 模板提供表单验证、CSRF 保护和渲染辅助功能。
创建表单
通过继承 AdvancedForm 并实现 fields() 方法来创建表单类:
import 'package:finch/finch_route.dart';
class RegisterForm extends AdvancedForm {
@override
List<FormField> fields() => [
FormField(
name: 'name',
label: '全名',
validators: [
FormValidator.required(),
FormValidator.minLength(2),
FormValidator.maxLength(100),
],
),
FormField(
name: 'email',
label: '电子邮箱',
validators: [
FormValidator.required(),
FormValidator.email(),
],
),
FormField(
name: 'password',
label: '密码',
validators: [
FormValidator.required(),
FormValidator.minLength(8),
],
),
];
}
表单验证
Future<String> register() async {
var form = RegisterForm();
await form.init(rq);
return form.check(
onValid: () async {
var name = form.getValue('name');
var email = form.getValue('email');
var password = form.getValue('password');
await UserModel().create({
'name': name,
'email': email,
'password': hashPassword(password),
});
return rq.redirect(url: '/dashboard');
},
onInvalid: () async {
return rq.renderView(
path: 'auth/register',
params: {'form': form},
);
},
);
}
验证器
| 验证器 | 描述 |
|---|---|
FormValidator.required() |
字段不能为空 |
FormValidator.email() |
必须是有效的电子邮件地址 |
FormValidator.minLength(n) |
至少 n 个字符 |
FormValidator.maxLength(n) |
最多 n 个字符 |
FormValidator.min(n) |
数值 ≥ n |
FormValidator.max(n) |
数值 ≤ n |
FormValidator.regex(pattern) |
必须匹配正则表达式 |
FormValidator.match('other') |
必须与另一个字段相等 |
FormValidator.custom(fn) |
自定义验证函数 |
CSRF 保护
AdvancedForm 自动处理 CSRF 验证。在模板中添加隐藏 input:
<form method="POST">
{{ form.csrfInput() }}
{# ... 表单字段 ... #}
<button type="submit">注册</button>
</form>
模板中的字段状态
form 对象提供字段状态和错误消息:
<div class="field {% if form.hasError('email') %}error{% endif %}">
<label>{{ form.getLabel('email') }}</label>
<input type="email" name="email" value="{{ form.getValue('email') }}">
{% if form.hasError('email') %}
<span class="error">{{ form.getError('email') }}</span>
{% endif %}
</div>
API 模式
对于 JSON 端点,当请求的 Content-Type 为 application/json 时,表单自动返回 JSON:
return form.check(
onValid: () async => rq.renderData(data: {'success': true}),
onInvalid: () async => rq.renderData(
data: {'errors': form.getErrors()},
statusCode: 422,
),
);