使用ng2-admin搭建成熟可靠的后台系统 -- ng2-admin(二)
使用ng2-admin搭建成熟可靠的后台系统 -- ng2-admin(二)1.构建动态表单
创建组件目录
在 项目目录结构如下,下面跟着步骤一步一步来构建
创建对象模型我们需要定义一个对象模型,用来描述表单功能需要的场景。相关功能非常之多(类似于 先创建一个最基础的基类,名为 export class QuestionBase<T>{ value: T; // 值,类型可选 key: string; // 字段名 label: string; // 控件前的文字提示 required: boolean; // 是否为必填 disabled: boolean; // 是否禁用 reg: string; // 正则 prompt: string; // 验证不通过提示 order: number; // 排序 controlType: string; // 渲染类型 constructor(options: { value?: T,key?: string,label?: string,required?: boolean,disabled?: boolean,reg?: string,prompt?: string,order?: number,controlType?: string } = {}) { // 设置各个值的默认值 this.value = options.value; this.key = options.key || ''; this.label = options.label || ''; this.required = !!options.required; this.disabled = !!options.disabled; this.reg = options.reg || ''; this.prompt = options.prompt || ''; this.order = options.order || 0; this.controlType = options.controlType || ''; } } 在这个基础上,我们派生出两个类 这么做的原因是根据不同的控件,进行个性化定制,以及合理规范,还有动态渲染出合适的组件
import { QuestionBase } from './question-base'; export class InputQuestion extends QuestionBase<string | number> { controlType = 'input'; type: string; constructor(options: {} = {}) { super(options); this.type = options['type'] || ''; } }
import { QuestionBase } from './question-base'; export class SelectQuestion extends QuestionBase<string | number> { controlType = 'select'; options: any[] = []; constructor(options: {} = {}) { super(options); this.options = options['options'] || []; } } 最后别忘了用 接下来,我们定义一个
import { Injectable } from '@angular/core'; import { FormControl,FormGroup,Validators } from '@angular/forms'; import { QuestionBase } from './dynamic-form-base'; @Injectable() export class QuestionControlService { constructor() { } // 转化为控件 toFormGroup(questions: QuestionBase<any>[]) { let group: any = {}; questions.forEach(question => { if (question.required) { // 选项为必填时 if (question.reg) { // 有正则的情况 group[question.key] = new FormControl(question.value || '',Validators.compose([Validators.required,Validators.pattern(question.reg)])); } else { group[question.key] = new FormControl(question.value || '',Validators.compose([Validators.required])); } } else if (!question.required && question.reg) { // 选项为非必填但是需要正则匹配的情况 group[question.key] = new FormControl(question.value || '',Validators.compose([Validators.pattern(question.reg)])); } else { group[question.key] = new FormControl(question.value || ''); } }); return new FormGroup(group); } } 动态表单组件现在我们已经有了一个定义好的完整模型了,接着就可以开始构建一个展现动态表单的组件。
<div> <form (ngSubmit)="onSubmit()" [formGroup]="form"> <div *ngFor="let question of questions" class="form-row"> <df-question [question]="question" [form]="form"></df-question> </div> <div class="form-row"> <button type="submit" [disabled]="!form.valid">保存</button> </div> </form> <div *ngIf="payload" class="form-row"> <strong>Saved the following values</strong><br>{{payload}} </div> </div>
import { Component,Input,OnInit } from '@angular/core'; import { FormGroup } from '@angular/forms'; import { QuestionBase } from './dynamic-form-base/question-base'; import { QuestionControlService } from './question-control.service'; @Component({ selector: 'dynamic-form',templateUrl: './dynamic-form.component.html',providers: [QuestionControlService] }) export class DynamicFormComponent implements OnInit { @Input() questions: QuestionBase<any>[] = []; form: FormGroup; payload = ''; constructor( private qcs: QuestionControlService ) { } ngOnInit() { console.log(this.questions); this.form = this.qcs.toFormGroup(this.questions); console.log(this.form); } onSubmit() { this.payload = JSON.stringify(this.form.value); } } 刚才创建的是一个组件入口,每个 现在来创建它的子组件
<div [formGroup]="form"> <div [ngSwitch]="question.controlType"> <input *ngSwitchCase="'input'" [formControlName]="question.key" [id]="question.key" [type]="question.type"> <select [id]="question.key" *ngSwitchCase="'select'" [formControlName]="question.key"> <option *ngFor="let opt of question.options" [value]="opt.value">{{opt.key}}</option> </select> </div> </div>
import { Component,Input } from '@angular/core'; import { FormGroup } from '@angular/forms'; import { QuestionBase } from '../dynamic-form-base/question-base'; @Component({ selector: 'df-question',templateUrl: './dynamic-form-question.component.html' }) export class DynamicFormQuestionComponent { @Input() question: QuestionBase<any>; @Input() form: FormGroup; get isValid() { return this.form.controls[this.question.key].valid } } 从上面的组件可以看出,未来需要添加组件时,只需要添加一种类型,可以用 在这两个组件中,我们依赖Angular的formGroup来把模板HTML和底层控件对象连接起来,该对象从问卷问题模型里获取渲染和验证规则。
注册组件我们创建组件之后,需要将我们的组件注册到
方法如下图,先引入
然后添加至
注册Service
要维护控件,只要非常简单的添加、更新和删除 切换到
import { Injectable } from '@angular/core'; import { QuestionBase,InputQuestion,SelectQuestion } from '../../../../theme/components/dynamic-form/dynamic-form-base'; @Injectable() export class UserAddService { getQuestions() { let questions: QuestionBase<any>[] = [ new SelectQuestion({ key: 'brave',label: 'Bravery Rating',value: 'solid',options: [ { key: 'Solid',value: 'solid' },{ key: 'Great',value: 'great' },{ key: 'Good',value: 'good' },{ key: 'Unproven',value: 'unproven' } ],order: 3 }),new InputQuestion({ key: 'firstName',label: 'First name',value: 'Bombasto',required: true,order: 1 }),new InputQuestion({ key: 'emailAddress',label: 'Email',type: 'email',order: 2 }) ]; return questions.sort((a,b) => a.order - b.order); } } 需要在
<h1> 新增用户组件 </h1> <div class="user-form"> <dynamic-form [questions]="UserAddQuestions"></dynamic-form> </div>
import { Component } from '@angular/core'; import { UserAddService } from './user-add.service'; import { QuestionBase } from '../../../../theme/components/dynamic-form/dynamic-form-base/question-base'; @Component({ selector: 'ngt-user-add',templateUrl: './user-add.component.html',providers: [UserAddService] }) export class UserAddComponent { public UserAddQuestions: QuestionBase<any>[] = []; constructor( private service: UserAddService ) { this.UserAddQuestions = this.service.getQuestions(); } } 然后打开浏览器,输入 访问效果如下图,填入一些数据,然后点击保存,我们需要存入的数据,显示在了下方
动态表单的雏形已经做出来了,现在还有几个问题
这些问题我们会在后续的章节慢慢解决,可以期待。 github地址 (分支 dynamic-form) 可以直接拉代码下来启动项目查看 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |