请先阅读:Angular 动态表单组件库ngx-formly使用说明(一)
expressionProperties
可以动态更改表单控件的其他属性
fields: FormlyFieldConfig[] = [
{
key: 'disabledControl',
type: 'checkbox',
defaultValue: false,
templateOptions: {
label: '禁用',
},
},
{
key: 'requiredControl',
type: 'checkbox',
defaultValue: false,
templateOptions: {
label: '必填',
},
},
{
key: 'hiddenControl',
type: 'checkbox',
defaultValue: false,
templateOptions: {
label: '隐藏',
},
},
{
key: 'text',
type: 'input',
templateOptions: {
label: '姓名',
},
expressionProperties: {
// 该表单控件templateOptions配置项disabled的值由表单控件disabledControl的值决定,从而控制是否禁用
'templateOptions.disabled': 'model.disabledControl',
// 该表单控件templateOptions配置项required的值由表单控件requiredControl的值决定,从而控制是否必填
'templateOptions.required': 'model.requiredControl',
// 该表单控件配置项hideExpression的值由表单控件requiredControl的值决定,从而控制是否隐藏,注意hideExpression可以接收的类型 boolean/string/function
hideExpression: 'model.hiddenControl',
// 或者配置项hide
hide: 'model.hiddenControl',
},
},
];
modelOptions
可配置表单控件的行为,如防抖,失去焦点时再更新model
等等
fields: FormlyFieldConfig[] = [
{
key: 'text',
type: 'input',
modelOptions: {
debounce: {
default: 2000, // 防抖
},
// updateOn: 'submit', // blur:失去焦点时更新,submit:提交时更新
},
templateOptions: {
label: 'modelOptions配置',
},
},
];
<form nz-form [nzLayout]="'vertical'" [formGroup]="form" (ngSubmit)="onSubmit()">
<formly-form
[form]="form"
[model]="model"
[fields]="fields"
[options]="options"
>
</formly-form>
<button nz-button nzType="primary" type="submit">提交</button>
<button nz-button nzType="danger" type="reset">重置</button> <!-- 推荐使用type类型为reset的按钮来重置表单 -->
<button nz-button nzType="primary" (click)="options.resetModel()">重置</button> <!-- 重置表单,但是内部会再次调用onSubmit方法 -->
<button nz-button nzType="primary" (click)="options.updateInitialValue()">更新初始化数据</button> <!-- 更新初始化数据后,调用options.resetModel重置表单回到初始化数据 -->
</form>
一般用于初始化或控制表单状态、数值等
options: FormlyFormOptions = {
formState: {
disabled: true,
options: [
{ label: '蛋糕', value: 1 },
{ label: '水果', value: 2 },
{ label: '咖啡', value: 3 },
]
},
};
fields: FormlyFieldConfig[] = [
{
key: 'text',
type: 'input',
templateOptions: {
label: '姓名',
},
expressionProperties: {
// 控件的禁用状态基于formState
'templateOptions.disabled': 'formState.disabled',
},
},
{
key: 'food',
type: 'select',
templateOptions: {
label: '食物',
},
expressionProperties: {
// select控件的options基于formState的options
'templateOptions.options': 'formState.options',
},
},
];
// 控制this.options.formState以控制表单控件的状态
toggleDisabled() {
this.options.formState.disabled = !this.options.formState.disabled;
}
在templateOptions
对象中可选配置:required
、min
、max
、minLength
、maxLength
、pattern
等
在validation
对象配置相对应的验证消息message
的内容
fields: FormlyFieldConfig[] = [
{
key: 'name',
type: 'input',
templateOptions: {
label: '姓名',
placeholder: '请输入姓名',
required: true, // 是否必填
min: 1, // 一般用于number输入框,最小数值不能小于min
max: 1000, // 一般用于number输入框,最大数值不能大于max
minLength: 1, // 限制最小长度
maxLength: 10, // 限制最大长度
pattern: /\d/, // 正则匹配
rows: 5, // 用于textarea表单控件
},
// 配置验证输出的message
validation: {
messages: {
required: '该项必填',
pattern: (error, field: FormlyFieldConfig) => `姓名"${field.formControl.value}" 不合法`,
max: (error, field: FormlyFieldConfig) => `最大数值不能超过"${field.templateOptions.max}"`,
},
},
},
];
在app.module
配置FormlyModule
实现全局配置内置验证的验证消息message
const maxValidationMessage = (err, field: FormlyFieldConfig): string => {
return `最大数值不能超过 ${field.templateOptions.max}`;
};
// app.module.ts
imports: [
// ...各种模块
FormlyModule.forRoot({
// name属性的值对应内置验证模块,message配置验证消息
validationMessages: [
{ name: 'required', message: '该项必填' },
{ name: 'max', message: maxValidationMessage },
],
}),
],
1.同步验证validators
fields: FormlyFieldConfig[] = [
{
key: 'name',
type: 'input',
templateOptions: {
label: '姓名',
placeholder: '请输入姓名',
required: true,
},
// 配置自定义同步验证器
validators: {
// name一般对应配置的表单控件key的值,或者自定义
name: {
// expression写验证逻辑,返回true时表示验证通过,否则验证不通过
expression: (formControl: FormControl) => !/\d/.test(formControl.value),
// 验证不通过时的提示消息,接收string或function
message: (error, field: FormlyFieldConfig) => `姓名"${field.formControl.value}"不合法!`
}
},
},
];
2.异步验证asyncValidators
fields: FormlyFieldConfig[] = [
{
key: 'name',
type: 'input',
templateOptions: {
label: '姓名',
placeholder: '请输入姓名',
required: true,
},
// 失去焦点时触发验证,一般用于异步验证,以提高性能
modelOptions: {
updateOn: 'blur',
},
// 配置自定义异步验证器
asyncValidators: {
nameValidator: {
// 需要返回promise对象,并resolve或reject一个boolean值,或者返回observable对象,比如of(true/flase)
expression: c => new Promise((resolve, reject) => {
setTimeout(() => {
resolve(!/\d/.test(c.value));
}, 2000);
}),
message: (error, field: FormlyFieldConfig) => `姓名"${field.formControl.value}"不合法!`
}
},
},
];
在app.module
配置FormlyModule
实现全局配置(比如全局配置身份证号码验证identityNum
)
// 身份证正则表达式
const idcardReg = /^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$|^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/
// 自定义验证器
const identityNumValidator = (control: FormControl): ValidationErrors {
return !control.value || idcardReg.test(control.value) ? null : { 'identityNum': true };
}
// 自定义验证消息
const identityNumValidatorMessage = (err, field: FormlyFieldConfig): string => {
return `“${field.formControl.value}”不是合法的身份证号码`;
};
// app.module.ts
imports: [
// ...各种模块
FormlyModule.forRoot({
validators: [
{ name: 'identityNum', validation: identityNumValidator },
],
validationMessages: [
{ name: 'identityNum', message: identityNumValidatorMessage },
],
}),
],
单选与多选
fields: FormlyFieldConfig[] = [
{
key: 'selectKey1',
type: 'select',
templateOptions: {
label: '普通选择',
options: [
{ label: '钢铁侠', value: 1001 },
{ label: '美国队长', value: 1002 },
{ label: '黑寡妇', value: 1003 },
{ label: '浩克', value: 1004 },
{ label: '女巫', value: 1005 },
],
},
},
{
key: 'selectKey2',
type: 'select',
templateOptions: {
label: '普通选择(options是Observable对象)',
options: of([
{ label: '钢铁侠', value: 1001 },
{ label: '美国队长', value: 1002 },
{ label: '黑寡妇', value: 1003 },
{ label: '浩克', value: 1004 },
{ label: '女巫', value: 1005 },
]),
},
},
{
key: 'selectKey3',
type: 'select',
templateOptions: {
label: '分组选择',
options: [
{ label: '钢铁侠', value: 1001, group: '男' },
{ label: '美国队长', value: 1002, group: '男' },
{ label: '黑寡妇', value: 1003, group: '女' },
{ label: '浩克', value: 1004, group: '男' },
{ label: '女巫', value: 1005, group: '女' },
],
},
},
{
key: 'selectKey4',
type: 'select',
templateOptions: {
label: '配置属性的分组选择',
options: [
{name: '钢铁侠', id: 1001, gender: '男'},
{name: '美国队长', id: 1002, gender: '男'},
{name: '黑寡妇', id: 1003, gender: '女'},
{name: '浩克', id: 1004, gender: '男'},
{name: '女巫', id: 1005, gender: '女'},
],
groupProp: 'gender',
valueProp: 'id',
labelProp: 'name',
},
},
{
key: 'selectKey5',
type: 'select',
templateOptions: {
label: '多选',
multiple: true,
options: [
{ label: '钢铁侠', value: 1001 },
{ label: '美国队长', value: 1002 },
{ label: '黑寡妇', value: 1003 },
{ label: '浩克', value: 1004 },
{ label: '女巫', value: 1005 },
],
},
},
];
级联选择I(省市区)
fields: FormlyFieldConfig[] = [
{
key: 'province',
type: 'select',
templateOptions: {
label: '省',
options: [
{ name: '广东省', id: 1 },
{ name: '湖南省', id: 2 },
],
valueProp: 'id',
labelProp: 'name',
},
},
{
key: 'city',
type: 'select',
templateOptions: {
label: '市',
options: [],
valueProp: 'id',
labelProp: 'name',
},
hooks: {
onInit: field => {
const cityList = [
{ id: 1, name: '广州市', provinceId: 1 },
{ id: 2, name: '深圳市', provinceId: 1 },
{ id: 3, name: '株洲市', provinceId: 2 },
{ id: 4, name: '长沙市', provinceId: 2 },
{ id: 5, name: '汕头市', provinceId: 1 },
];
const provinceControl = this.form.get('province');
field.templateOptions.options = provinceControl.valueChanges.pipe(
tap(() => field.formControl.setValue(null)),
map(id => cityList.filter(city => city.provinceId === id)),
);
},
},
},
{
key: 'area',
type: 'select',
templateOptions: {
label: '区',
options: [],
valueProp: 'id',
labelProp: 'name',
},
hooks: {
onInit: field => {
const areaList = [
{ id: 1, name: '福田区', cityId: 2 },
{ id: 2, name: '天河区', cityId: 1 },
{ id: 3, name: '南山区', cityId: 2 },
{ id: 4, name: '潮阳区', cityId: 5 },
{ id: 5, name: '白云区', cityId: 1 },
{ id: 6, name: '芙蓉区', cityId: 4 },
{ id: 7, name: '荷塘区', cityId: 3 },
{ id: 8, name: '石峰区', cityId: 3 },
{ id: 9, name: '宝安区', cityId: 2 },
{ id: 10, name: '雨花区', cityId: 4 },
];
const cityControl = this.form.get('city');
field.templateOptions.options = cityControl.valueChanges.pipe(
tap(() => field.formControl.setValue(null)),
map(id => areaList.filter(area => area.cityId === id)),
);
},
},
},
];
级联选择II(省市区)
options: FormlyFormOptions = {
formState: {
provinceList: [
{ name: '广东省', id: 1 },
{ name: '湖南省', id: 2 },
],
cityList: [
{ id: 1, name: '广州市', provinceId: 1 },
{ id: 2, name: '深圳市', provinceId: 1 },
{ id: 3, name: '株洲市', provinceId: 2 },
{ id: 4, name: '长沙市', provinceId: 2 },
{ id: 5, name: '汕头市', provinceId: 1 },
],
areaList: [
{ id: 1, name: '福田区', cityId: 2 },
{ id: 2, name: '天河区', cityId: 1 },
{ id: 3, name: '南山区', cityId: 2 },
{ id: 4, name: '潮阳区', cityId: 5 },
{ id: 5, name: '白云区', cityId: 1 },
{ id: 6, name: '芙蓉区', cityId: 4 },
{ id: 7, name: '荷塘区', cityId: 3 },
{ id: 8, name: '石峰区', cityId: 3 },
{ id: 9, name: '宝安区', cityId: 2 },
{ id: 10, name: '雨花区', cityId: 4 },
]
}
};
fields: FormlyFieldConfig[] = [
{
key: 'province',
type: 'select',
templateOptions: {
label: '省',
options: [],
valueProp: 'id',
labelProp: 'name',
},
expressionProperties: {
'templateOptions.options': 'formState.provinceList'
},
},
{
key: 'city',
type: 'select',
templateOptions: {
label: '市',
options: [],
valueProp: 'id',
labelProp: 'name',
},
expressionProperties: {
'templateOptions.options': 'formState.cityList.filter(city => city.provinceId === model.province)',
'model.city': `field.templateOptions.options.find(city => city.id === model.city) ? model.city : null`,
},
},
{
key: 'area',
type: 'select',
templateOptions: {
label: '区',
options: [],
valueProp: 'id',
labelProp: 'name',
},
expressionProperties: {
'templateOptions.options': 'formState.areaList.filter(area => area.cityId === model.city)',
'model.area': `field.templateOptions.options.find(area => area.id === model.area) ? model.area : null`,
},
},
];
参考文献: