

formly-form 动态表单 - 猫神甜辣酱
source link: https://www.cnblogs.com/fangdongdemao/p/16992806.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

动态表单库
https://github.com/ngx-formly/ngx-formly
ng add @ngx-formly/schematics --ui-theme=ng-zorro-antd
@ngx-formly/ng-zorro-antd
-
-
bootstrap
material
ng-zorro-antd
ionic
primeng
kendo
nativescript
-
会默认导入到Module
+ import { ReactiveFormsModule } from '@angular/forms'; + import { FormlyModule } from '@ngx-formly/core'; + import { FormlyBootstrapModule } from '@ngx-formly/bootstrap'; @NgModule({ imports: [ BrowserModule, + FormsModule, + ReactiveFormsModule, // ----------- FormlyNgZorroAntdModule, NzFormModule, // ------- + FormlyModule.forRoot(), + FormlyBootstrapModule ], ... })
formly-form
<formly-form [form]="form" [fields]="fields" [model]="model"></formly-form>
该<formly-form>
组件是表单的主要容器
fields
:用于构建表单的字段配置。form
:允许跟踪模型值和验证状态的表单实例。model
:表格要表示的模型
form = new FormGroup({}); model = { email: '[email protected]' }; fields: FormlyFieldConfig[] = [ { key: 'email', type: 'input', props: { label: 'Email address', placeholder: 'Enter email', required: true, } } ];
Name | Type | Default | Required | Description |
---|---|---|---|---|
form | FormGroup or FormArray |
new FormGroup({}) |
no | 表单实例 |
fields | FormlyFieldConfig[] |
yes | 构建表单的字段配置 | |
model | any |
yes | 表单表示的模型 | |
options | FormlyFormOptions |
no | 表格的选项 |
(modelChange)
model 值发生变量的时候触发的事件
fields
Attribute | Type | Description |
---|---|---|
key | string |
model 的键 |
id | string |
请注意,id 如果未设置,则会生成。 |
name | string |
过于的表单name才有效 |
type | string |
自定义模板 |
className | string |
自定的class样式formly-field directive. |
props | object |
任何特定于模板的选项都放在此处 |
templateOptions | object |
任何特定于模板的选项都放在此处,props 进行改用(props权重高一些) |
template | string |
自定义html 内容, 而不是type |
defaultValue | any |
model 为设置,或者为undefined , 该模型的值被分配 |
hide | boolean |
是否隐藏字段 |
hideExpression | boolean /string /function |
有条件地隐藏该字段 |
expressions | boolean /string /function |
一个对象,其中键是要在主字段配置上设置的属性,值是用于分配该属性的表达式。 |
focus | boolean |
是否获取焦点. 默认为 false . 可以用 expressions 进行设置 |
wrappers | string[] |
自定义组件里面包装label , 可以设置样式 |
parsers | function[] |
每当模型更新(通常通过用户输入)时,作为管道执行的函数数组 |
fieldGroup | FormlyFieldConfig[] |
字段组, 让高级布局更简单, 对于通过模型关联的字段进行分组 |
fieldArray | FormlyFieldConfig |
|
fieldGroupClassName | string |
formly-group 组件的class |
validation | object |
校验messages 信息的显示 |
validators | any |
特定字段设置验证规则 |
asyncValidators | any |
异步验证的内容 |
formControl | AbstractControl |
该字段的FormControl。它为您提供更多控制,如运行验证器、计算状态和重置状态。 |
modelOptions | object |
控制模型更改的有用属性的对象: debounce , updateOn |
modelOptions?: { debounce?: { // 防抖的ms 值 default: number; }; // https://angular.io/api/forms/AbstractControl#updateOn 触发方式 updateOn?: 'change' | 'blur' | 'submit'; };
formState
配合option
进行状态通信
NgModule 声明中声明验证函数和消息
自定义校验
// 自定义报错信息 export function IpValidatorMessage(error: any, field: FormlyFieldConfig) { return `"${field.formControl.value}" is not a valid IP Address`; } // 报错规则 export function IpValidator(control: AbstractControl): ValidationErrors | null { return /(\d{1,3}\.){3}\d{1,3}/.test(control.value) ? null : { 'ipTwo': true }; } ... @NgModule({ imports: [ ... FormlyModule.forRoot({ validationMessages: [ { name: 'ipTwo', message: IpValidatorMessage }, { name: 'required', message: 'This field is required' }, ], validators: [ { name: 'ipTwo', validation: IpValidator }, ], }), ] })
页面上使用
{ key: 'ip', type: 'input', props: { label: 'IP Address (using custom validation declared in ngModule)', required: true, }, validators: { validation: ['ipTwo'], }, // 异步校验器 asyncValidators: { validation: ['ipAsync'], }, },
字段声明校验函数
export function IpValidator(control: AbstractControl): ValidationErrors { return /(\d{1,3}\.){3}\d{1,3}/.test(control.value) ? null : { 'ipTwo': true }; } { key: 'ip', type: 'input', props: { label: 'IP Address (using custom validation through `validators.validation` property)', required: true, }, validators: { validation: [IpValidator], }, // 异步函数 asyncValidators: { validation: [IpAsyncValidator], }, },
在字段定义中声明验证函数和消息
{ key: 'ip', type: 'input', props: { label: 'IP Address (using custom validation through `validators.expression` property)', description: 'custom validation message through `validators.expression` property', required: true, }, validators: { ip: { // 为true 为符合报错信息 expression: (c: AbstractControl) => /(\d{1,3}\.){3}\d{1,3}/.test(c.value), message: (error: any, field: FormlyFieldConfig) => `"${field.formControl.value}" is not a valid IP Address`, }, }, asyncValidators: { ip: { expression: (c: AbstractControl) => return new Promise((resolve, reject) => { setTimeout(() => { resolve(/(\d{1,3}\.){3}\d{1,3}/.test(c.value)); }, 1000); }), message: (error: any, field: FormlyFieldConfig) => `"${field.formControl.value}" is not a valid IP Address`, }, }, },
在 NgModule 声明中的表单类型和消息中声明验证函数
export function IpValidator(control: AbstractControl): boolean { return /(\d{1,3}\.){3}\d{1,3}/.test(control.value); } @NgModule({ imports: [ ... FormlyModule.forRoot({ validationMessages: [ { name: 'ipTwo', message: 'This field is required' }, ], types: [ { name: 'ipTwo', extends: 'input', defaultOptions: { validators: { ip: IpValidator // 'ip' matches the ip validation message } }, }, }), ] })
形式表达式expression
{ key: 'text2', type: 'input', props: { label: 'Hey!', placeholder: 'This one is disabled if there is no text in the other input', }, expressions: { 'props.disabled': '!model.text', 'props.disabled': (field: FormlyFieldConfig) => { return !field.model.text; }, }, },
{ key: 'iLikeTwix', type: 'checkbox', props: { label: 'I like twix', }, expressions: { hide: '!model.name', hide: (field: FormlyFieldConfig) => { return field.model?.city === "123"; }, }, }
toggle(){ this.fields[0].hide = !this.fields[0].hide; }
formState 状态
<formly-form [model]="model" [fields]="fields" [options]="options" [form]="form"></formly-form>
form = new FormGroup({}); model: any = {}; options: FormlyFormOptions = { formState: { disabled: true, }, }; fields: FormlyFieldConfig[] = [ { key: 'text', type: 'input', props: { label: 'First Name', }, expressions: { // apply expressionProperty for disabled based on formState 'props.disabled': 'formState.disabled', }, }, ]; toggleDisabled() { this.options.formState.disabled = !this.options.formState.disabled; }
hooks: { afterContentInit: () => {}, afterViewInit: () => {}, onInit: () => {}, onChanges: () => {}, onDestroy: () => {}, },
export type FormlyHookFn = (field: FormlyFieldConfig) => void; export interface FormlyHookConfig { onInit?: FormlyHookFn; onChanges?: FormlyHookFn; afterContentInit?: FormlyHookFn; afterViewInit?: FormlyHookFn; onDestroy?: FormlyHookFn; }
hooks:{ onInit(f: FormlyFieldConfigCache) { f.formControl = new FormControl(); } }, }
fieldChanges
值得监听(源码是对valueChanges
进行封装)
hooks: { onInit(f: FormlyFieldConfigCache) { f?.options?.fieldChanges?.subscribe(res => { console.log(res,'ressss'); }) } }, modelOptions: { debounce: {default: 3000},// 防抖 updateOn: 'change' }
自定义组件
import { Component } from '@angular/core'; import { FieldType, FieldTypeConfig } from '@ngx-formly/core'; @Component({ selector: 'formly-field-input', template: ` <input type="input" [formControl]="formControl" [formlyAttributes]="field"> `, }) export class InputFieldType extends FieldType<FieldTypeConfig> {}
ngModule 注册组件
@NgModule({ declarations: [InputFieldType], import { InputFieldType } from './intput-field.type'; @NgModule({ imports: [ FormlyModule.forRoot({ types: [ { name: 'inputOne', component: InputFieldType }, ], }), ], })
types 有两个属性
name:组件类型的名称。type您在字段的选项中使用它。 component:设置此类型时 Formly 应创建的组件。
方式一, 直接把组件传递给字段使用
fields: FormlyFieldConfig[] = [ { key: 'firstname', type: InputFieldType, }, ];
方式二, 使用ngModule 注册的type
fields: FormlyFieldConfig[] = [ { key: 'firstname', type: 'inputOne', }, ];
自定义label 组件
创建一个代表扩展FieldWrapper
类的包装器的组件。
import { Component, ViewChild, ViewContainerRef } from '@angular/core'; import { FieldWrapper } from '@ngx-formly/core'; @Component({ selector: 'formly-wrapper-panel', template: ` <div class="card"> <h3 class="card-header">Its time to party</h3> <h3 class="card-header">{{ props.label }}</h3> <div class="card-body"> <ng-container #fieldComponent></ng-container> </div> <!-- 报错的信息 --> <ng-container *ngIf="showError"> <formly-validation-message [field]="field"></formly-validation-message> </ng-container> </div> `, }) export class PanelFieldWrapper extends FieldWrapper { }
@NgModule({ declarations: [PanelFieldWrapper], imports: [ FormlyModule.forRoot({ wrappers: [ { name: 'panel', component: PanelFieldWrapper }, ], }), ], })
方式一 直接传递组件
fields: FormlyFieldConfig[] = [ { key: 'address', wrappers: [PanelFieldWrapper], props: { label: 'Address' }, fieldGroup: [{ key: 'town', type: 'input', props: { required: true, type: 'text', label: 'Town', }, }], }, ];
方法二:将PanelFieldWrapper
别名(在 中定义FormlyModule.forRoot
)传递给字段配置。
fields: FormlyFieldConfig[] = [ { key: 'address', + wrappers: ['panel'], props: { label: 'Address' }, fieldGroup: [{ key: 'town', type: 'input', props: { required: true, type: 'text', label: 'Town', }, }], }, ];
在module组合使用
@NgModule({ imports: [ FormlyModule.forRoot({ types: [ { name: 'operator', component: OperatorComponent, //输入框组件 wrappers: ['form-field'] //label 组件 }, ], }), ],
自定义扩展接口属性
创建了一个扩展,它定义了一个默认标签(如果它FormlyFieldConfig
本身没有定义的话)
定义接口类
*default-label-extension.ts*
import { FormlyExtension } from '@ngx-formly/core'; export const defaultLabelExtension: FormlyExtension = { prePopulate(field): void { if (field.props?.label) { return; } field.props = { ...field.props, label: 'Default Label' } }, };
FormlyExtension
允许您定义最多三个方法,这些方法将在表单构建过程中按此顺序调用:
prePopulate
onPopulate
postPopulate
注册自定义扩展
@NgModule({ imports: [ FormlyModule.forRoot({ extensions: [ { name: 'default-label', extension: defaultLabelExtension, priority:1 // 优先级, 默认1 } ] }) ], })
lazyRender 延迟加载组件
默认为true
当设置为false, 渲染字段组件并使用CSS控制其可见性。
constructor( private config: FormlyConfig, ) { this.config.extras.lazyRender = false; } fields: FormlyFieldConfig[] = [ { key: 'input', type: 'input', hide:true, // 设置为true,隐藏, 我们发现是通过css隐藏的 templateOptions: { label: 'Input', placeholder: 'Input placeholder', required: true, }, }, ]
renderFormlyFieldElement
是否呈现渲染每项中<form-field>
组件里面的dom
默认为true
// 我们发现里面的内容都被隐藏啦 this.config.extras.renderFormlyFieldElement = false;
我们发现form-field
组件的内容会提取到外层
异步修改值
{ key: 'input', type: 'input', props: { label: '测试1' }, expressions: { 'props.label':timer(2000).pipe( map(()=>'修改为2') ) }, }
修改一项的值
ngOnInit(): void { setTimeout(()=>{ this.fields[0]?.formControl?.setValue('aaaa'); console.log(this.model); },2000) }
key 支持括号/点的方式拿到属性
fields: FormlyFieldConfig[] = [{ key: 'name[0].age', type: 'textarea', className: 'flex-1', }] model = {name: [{age: 'sexName'}]};
fields: FormlyFieldConfig[] = [ // 多选 { key: 'Select', type: 'select', props: { label: 'Select', placeholder: 'Placeholder', description: 'Description', required: true, options: [ { value: 1, label: 'Option 1' }, { value: 2, label: 'Option 2' }, { value: 3, label: 'Option 3' }, { value: 4, label: 'Option 4', disabled: true }, ], }, }, // 多选 { key: 'select_multi', type: 'select', props: { label: 'Select Multiple', placeholder: 'Placeholder', description: 'Description', required: true, multiple: true, selectAllOption: 'Select All', options: [ { value: 1, label: 'Option 1' }, { value: 2, label: 'Option 2' }, { value: 3, label: 'Option 3' }, { value: 4, label: 'Option 4', disabled: true }, ], }, }, ];
fields: FormlyFieldConfig[] = [ { key: 'Radio', type: 'radio', props: { label: 'Radio', placeholder: 'Placeholder', description: 'Description', required: true, options: [ { value: 1, label: 'Option 1' }, { value: 2, label: 'Option 2' }, { value: 3, label: 'Option 3' }, { value: 4, label: 'Option 4', disabled: true }, ], }, }, ];
fields: FormlyFieldConfig[] = [ { key: 'Checkbox', type: 'checkbox', props: { label: 'Accept terms', description: 'In order to proceed, please accept terms', pattern: 'true', required: true, }, validation: { messages: { pattern: 'Please accept the terms', }, }, }, ];
fields: FormlyFieldConfig[] = [ { key: 'Textarea', type: 'textarea', props: { label: 'Textarea', placeholder: 'Placeholder', description: 'Description', required: true, }, }, ];
fields: FormlyFieldConfig[] = [ { key: 'Input', type: 'input', props: { label: 'Input', placeholder: 'Placeholder', description: 'Description', required: true, }, }, ];
__EOF__
Recommend
-
137
辣味的XO酱,能不能征服你的味蕾?
-
46
到2020年,辣酱行业将释放出400亿的市场规模。
-
26
本文来自微信公众号:
-
12
目前,老干妈占据国内辣椒酱市场约1/5的份额;李锦记和辣妹子分别占比9.7%和9.2%,位列第二、第三。辣酱行业正迎来变局,新锐品牌虎邦、...
-
8
作者:陈大鱼头github: KRISACHAN鱼头曾在 『极限版』不掺水,用纯 CSS 来实现超飒的表单验...
-
7
Form表单的重置 ...
-
6
掌握element-ui中表单校验的使用 基本步骤-共三步定义验证规则。data()中按格式定义规则在模板上做属性配置来应用规则(三个配置)给表单设置 rules 属性传入验证规...
-
3
-
6
老干妈真的“老”了?新兴品牌奔袭辣酱市场,陶华碧急需一场大变革
-
1
辣酱下半场,开打网红战? ...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK