动态表单生成之拖拽生成表单(下)

我们的动态表单,最终要实现的效果与Form.io的在线生成表单的效果类似,可以参考它的demo地址:https://codepen.io/travist/full/xVyMjo

准备工作

首先,我们在过程中会需要用到一个弹出层控件,这里引用KendoUI的Dialogs,使用下面的命令安装:

npm i --save @progress/kendo-angular-dialog

安装完成后,会提示几个可选依赖没有安装,我们继续使用命令完成安装:

npm i --save @progress/kendo-angular-buttons jquery popper.js

然后,我们将上一个列子中的动态表单的相关代码Copy过来,用于我们本次动态表单的生成,首先是HTML中的代码,我们将它放到拖拽释放区域,代码如下:

<div class="col-md-8">
<h4>请将表单元素拖拽到这里</h4> <div style="min-height: 300px;background-color: #EDEDEE" droppable (onDrop)="onDropToForm($event)">
<form [formGroup]="formGroup" class="k-form">
<dynamic-kendo-form [group]="formGroup"
[model]="formModel"
> </dynamic-kendo-form>
</form>
</div>
</div>

然后,我们我们将Component中的相关代码删掉FormModel中的具体控件的定义后复制过来,代码如下:

formModel: DynamicFormControlModel[] = [];
formGroup: FormGroup; constructor(private formService: DynamicFormService) {
} ngOnInit() {
this.formGroup = this.formService.createFormGroup(this.formModel);
}

好,准备工作到此完成。

动态添加文本框到表单中

下面,我们来实现将文本框添加到表单中。大概流程是这样的,当我们将文本框控件拖拽到表单中时,弹出一个窗口,让用户输入文本框的Id、Label、Placeholder,然后点击保存后,我们将文本框按用户输入的属性动态的添加到表单中。

我们一步步来~

首先,定义一个弹出窗口,并定义了一些属性和方法绑定到这个窗口中,其中:

textboxWindowIsOpen属性来绑定窗口是否可见

closeTextboxWindow方法用于关闭窗口

saveTextBox方法用于用户点击保存按钮后的动态添加控件到表单的相关事件处理

Id,Label,Placeholder文本框均与txtBox的相关属性绑定,txtBox属性的类型为DynamicInputModel,即ng-dynamic-forms中定义的文本框的类型。

<kendo-window title="请输入表单元素属性" *ngIf="textboxWindowIsOpen" (close)="closeTextboxWindow()"
[minWidth]="250" [width]="450"> <form class="k-form"> <label class="k-form-field">
<span>ID</span>
<input class="k-textbox" placeholder="Text Box Id" name="id" [(ngModel)]="txtBox.id"/>
</label>
<label class="k-form-field">
<span>Label</span>
<input class="k-textbox" placeholder="Text Box Label" name="label" [(ngModel)]="txtBox.label"/>
</label>
<label class="k-form-field">
<span>Placeholder</span>
<input class="k-textbox" placeholder="Text Box Placeholder" name="placeholder" [(ngModel)]="txtBox.placeholder"/>
</label> <div class="text-right">
<button type="button" class="k-button" (click)="closeTextboxWindow()">关闭</button>
<button type="button" class="k-button k-primary" (click)="saveTextBox()">保存</button>
</div>
</form> </kendo-window>

然后让我们来看看最终ts代码中逻辑的实现吧:

首先是属性的定义:

textboxWindowIsOpen = false;
txtBox: DynamicInputModel = new DynamicInputModel({});

其次当文本框控件拖拽到表单区域时,由上篇中提到的onDrop时间的触发来打开上面定义的window:

onDropToForm(event) {
switch (event.dragData.type) {
case 'TextBox':
this.openTextboxWindow();
break;
default:
break;
}
}

打开和关闭window的方法其实就是修改了如下textboxWindowIsOpen属性的值:

openTextboxWindow() {
this.textboxWindowIsOpen = true;
} closeTextboxWindow() {
this.textboxWindowIsOpen = false;
}

最后,当用户点击保存时,动态添加文本框到表单中:

saveTextBox() {
const newTxtbox = new DynamicInputModel({
id: this.txtBox.id,
label: this.txtBox.label,
placeholder: this.txtBox.placeholder
}); this.formModel.push(newTxtbox);
this.formGroup = this.formService.createFormGroup(this.formModel);
this.closeTextboxWindow();
}

保存的这段代码中,有两个点需要注意:

1.不能直接将我们定义的txtBox属性push到formModel中,因为txtBox是对象,为引用类型,而我们的txtBox是一个公用的对象,如果直接push该对象,则后续该对象发生变化,formModel中的该对象也会跟着变。

2.push完成后,必须再次使用formService创建表单,这里的原因我也没有找到,不这样做会报错~

this.formGroup = this.formService.createFormGroup(this.formModel);

Show Demo

让我们来看看效果吧(这只是个Demo,有非常明显的Bug还请大家见谅)

另外,对于其他的控件,其实原理都是一样的,只是在弹出的窗口中的属性不同而已,这里提供给大家思路,如果我把这些元素都实现了,我会放出来给大家~

代码

拖拽相关的所有代码打包如下:

  1 <div style="padding:20px;">
2 <div class="row" style="margin-top:20px;border: 1px solid;padding:10px;">
3 <div class="col-md-4">
4 <ul class="list-group">
5 <li class="list-group-item" draggable [dragData]="{type:'TextBox'}">TextBox</li>
6 <li class="list-group-item" draggable [dragData]="{type:'Select'}">Select</li>
7 <li class="list-group-item" draggable [dragData]="{type:'TextArea'}">TextArea</li>
8 <li class="list-group-item" draggable [dragData]="{type:'Password'}">Password</li>
9 <li class="list-group-item" draggable [dragData]="{type:'Number'}">Number</li>
10 </ul>
11 </div>
12 <div class="col-md-8">
13 <h4>请将表单元素拖拽到这里</h4>
14
15 <div style="min-height: 300px;background-color: #EDEDEE" droppable (onDrop)="onDropToForm($event)">
16 <form [formGroup]="formGroup" class="k-form">
17 <dynamic-kendo-form [group]="formGroup"
18 [model]="formModel"
19 >
20
21 </dynamic-kendo-form>
22 </form>
23 </div>
24 </div>
25 </div>
26 </div>
27
28 <kendo-window title="请输入表单元素属性" *ngIf="textboxWindowIsOpen" (close)="closeTextboxWindow()"
29 [minWidth]="250" [width]="450">
30
31 <form class="k-form">
32
33 <label class="k-form-field">
34 <span>ID</span>
35 <input class="k-textbox" placeholder="Text Box Id" name="id" [(ngModel)]="txtBox.id"/>
36 </label>
37 <label class="k-form-field">
38 <span>Label</span>
39 <input class="k-textbox" placeholder="Text Box Label" name="label" [(ngModel)]="txtBox.label"/>
40 </label>
41 <label class="k-form-field">
42 <span>Placeholder</span>
43 <input class="k-textbox" placeholder="Text Box Placeholder" name="placeholder" [(ngModel)]="txtBox.placeholder"/>
44 </label>
45
46 <div class="text-right">
47 <button type="button" class="k-button" (click)="closeTextboxWindow()">关闭</button>
48 <button type="button" class="k-button k-primary" (click)="saveTextBox()">保存</button>
49 </div>
50 </form>
51
52 </kendo-window>
53

kendo-ui-drag-drop.component.html

  1 import {Component, OnInit} from '@angular/core';
2 import {DynamicFormControlModel, DynamicFormService, DynamicInputModel} from "@ng-dynamic-forms/core";
3 import {FormGroup} from "@angular/forms";
4
5 @Component({
6 selector: 'app-kendo-ui-drag-drop',
7 templateUrl: './kendo-ui-drag-drop.component.html',
8 styleUrls: ['./kendo-ui-drag-drop.component.css']
9 })
10 export class KendoUiDragDropComponent implements OnInit {
11
12 textboxWindowIsOpen = false;
13 txtBox: DynamicInputModel = new DynamicInputModel({});
14 formModel: DynamicFormControlModel[] = [];
15 formGroup: FormGroup;
16
17 constructor(private formService: DynamicFormService) {
18 }
19
20
21 ngOnInit() {
22 this.formGroup = this.formService.createFormGroup(this.formModel);
23 }
24
25 onDropToForm(event) {
26 switch (event.dragData.type) {
27 case 'TextBox':
28 this.openTextboxWindow();
29 break;
30 default:
31 break;
32 }
33 }
34
35 openTextboxWindow() {
36 this.textboxWindowIsOpen = true;
37 }
38
39 closeTextboxWindow() {
40 this.textboxWindowIsOpen = false;
41 }
42
43 saveTextBox() {
44 const newTxtbox = new DynamicInputModel({
45 id: this.txtBox.id,
46 label: this.txtBox.label,
47 placeholder: this.txtBox.placeholder
48 });
49
50 this.formModel.push(newTxtbox);
51 this.formGroup = this.formService.createFormGroup(this.formModel);
52 this.closeTextboxWindow();
53 }
54 }
55

kendo-ui-drag-drop.component.ts

Angular动态表单生成(八)的更多相关文章

  1. Angular动态表单生成(七)

    动态表单生成之拖拽生成表单(上) 这个功能就比较吊炸天了,之前的六篇,都是ng-dynamic-forms自带的功能,可能很多的说明官方的文档都已经写了,我只是个搬运工,而在这篇文章中,我将化身一个工 ...

  2. Angular动态表单生成(一)

    好久不写博客了,手都生了,趁着最近老大让我研究动态表单生成的时机,撸一发博客~~ 开源项目比较 老大丢给我了两个比较不错的开源的动态表单生成工具,这两个项目在github上的star数量基本持平: h ...

  3. Angular动态表单生成(五)

    动态表单生成之布局 到上面的篇章为止,我们已经把表单比较完整的生成出来了,也实现了一些验证功能,可以说,我们截止这里,就已经可以满足我们的大部分表单生成需求了~ 但是: 目前来说,我们对于表单的布局只 ...

  4. Angular动态表单生成(六)

    动态表单之根据Json生成表单 我们在实际的使用中,动态表单往往是由服务器端的一系列配置,然后返回数据给客户端,最后客户端根据数据来动态的生成表单.那么怎么像我们上面所描述的这样,生成一个可以让我们的 ...

  5. Angular动态表单生成(二)

    ng-dynamic-forms源码分析 在两个开源项目中,ng-dynamic-forms的源码相较于form.io,比较简单,所以我还勉强能看懂,下面就我自己的理解进行简单分析,若有不对的地方,请 ...

  6. Angular动态表单生成(三)

    ng-dynamic-forms实践篇(上) 定个小目标 先来定个小目标吧,我们要实现的效果: 动态生成一个表单,里面的字段如下: 字段名称 字段类型 验证 备注 姓名 text 必填,长度小于15 ...

  7. Angular动态表单生成(四)

    ng-dynamic-forms实践篇(下) 我们接着上篇,先把小目标中的所有字段都定义出来 这部分就是苦力活儿了,把KendoUiComponent中的formModel完善即可: formMode ...

  8. form-create 3.0 版本发布,好用的Vue3版本动态表单生成组件

    form-create 是一个可以通过 JSON 生成具有动态渲染.数据收集.验证和提交功能的表单生成组件.支持2个UI框架,并且支持生成任何 Vue 组件.内置20种常用表单组件和自定义组件,再复杂 ...

  9. Vue+Element的动态表单,动态表格(后端发送配置,前端动态生成)

    Vue+Element的动态表单,动态表格(后端发送配置,前端动态生成) 动态表单生成 ElementUI官网引导 Element表单生成 Element动态增减表单,在线代码 关键配置 templa ...

随机推荐

  1. CSS-带尖角的对话框

    效果图: box1的代码: .box{ position: relative; width: 200px; height: 200px; border: 2px solid #000; backgro ...

  2. 浅谈 JavaScript 中常用数据及其类型转换

    在 JavaScript 中有一些 value 会经常碰到: [] (空数组).{} (空对象).'' (空字符串).undefined.null.0.NaN.Infinite 也会经常碰到数据类型转 ...

  3. oracle 删除表的几种方法及回收站

    1.删除表结构和表数据 drop table 表名 [purge]  purge表示不放入回收站 2.删除表数据 delete from 表名 [where ...] 特点:高水位线不降:记录日志,速 ...

  4. Selectivizr-让IE6~8支持CSS3伪类和属性选择器

    一.下载和demo 下载: 您可以狠狠地点击这里:selectivizr-1.0.0.zip(右键-[目标|链接另存为] 9.24K) demo: 您可以狠狠地点击这里:Selectivizr部分属性 ...

  5. 通过代码管理工具 git 完成一次完整的代码管理过程

    1.从公共远程fork一份自己的本地远程之后,从本地远程 clone 到本地 2.将本地代码跟公共远程代码做关联配置 git remote add upstream https://github.co ...

  6. Sun Solairs系统添加裸设备

    Sun Solaris系统添加裸设备对表空间进行扩容的大体操作步骤. 1.查看当前卷组信息 --查看当前卷组信息#vxdg list --查看当前卷组中物理磁盘的使用情况#vxdg free |gre ...

  7. deep learning深度学习之学习笔记基于吴恩达coursera课程

    feature study within neural network 在regression问题中,根据房子的size, #bedrooms原始特征可能演算出family size(可住家庭大小), ...

  8. Oracle EBS 更新客户地点

    --更新客户地点 declare x_return_status ); x_msg_count NUMBER; x_msg_data ); x_profile_id NUMBER; l_locatio ...

  9. java虚拟机---内存

    java虚拟机---内存 Java虚拟机,即JVM,负责运行java程序,每个java程序都运行在一个具体jvm实例上.Java虚拟机的体系架构分为:类装载子系统.运行时数据区.执行引擎.类装载子系统 ...

  10. 转:Window_Open详解

       引:Window_Open详解一.window.open()支持环境:JavaScript1.0+/JScript1.0+/Nav2+/IE3+/Opera3+ 二.基本语法:window.op ...