Angular动态表单生成(八)
动态表单生成之拖拽生成表单(下)
我们的动态表单,最终要实现的效果与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动态表单生成(八)的更多相关文章
- Angular动态表单生成(七)
动态表单生成之拖拽生成表单(上) 这个功能就比较吊炸天了,之前的六篇,都是ng-dynamic-forms自带的功能,可能很多的说明官方的文档都已经写了,我只是个搬运工,而在这篇文章中,我将化身一个工 ...
- Angular动态表单生成(一)
好久不写博客了,手都生了,趁着最近老大让我研究动态表单生成的时机,撸一发博客~~ 开源项目比较 老大丢给我了两个比较不错的开源的动态表单生成工具,这两个项目在github上的star数量基本持平: h ...
- Angular动态表单生成(五)
动态表单生成之布局 到上面的篇章为止,我们已经把表单比较完整的生成出来了,也实现了一些验证功能,可以说,我们截止这里,就已经可以满足我们的大部分表单生成需求了~ 但是: 目前来说,我们对于表单的布局只 ...
- Angular动态表单生成(六)
动态表单之根据Json生成表单 我们在实际的使用中,动态表单往往是由服务器端的一系列配置,然后返回数据给客户端,最后客户端根据数据来动态的生成表单.那么怎么像我们上面所描述的这样,生成一个可以让我们的 ...
- Angular动态表单生成(二)
ng-dynamic-forms源码分析 在两个开源项目中,ng-dynamic-forms的源码相较于form.io,比较简单,所以我还勉强能看懂,下面就我自己的理解进行简单分析,若有不对的地方,请 ...
- Angular动态表单生成(三)
ng-dynamic-forms实践篇(上) 定个小目标 先来定个小目标吧,我们要实现的效果: 动态生成一个表单,里面的字段如下: 字段名称 字段类型 验证 备注 姓名 text 必填,长度小于15 ...
- Angular动态表单生成(四)
ng-dynamic-forms实践篇(下) 我们接着上篇,先把小目标中的所有字段都定义出来 这部分就是苦力活儿了,把KendoUiComponent中的formModel完善即可: formMode ...
- form-create 3.0 版本发布,好用的Vue3版本动态表单生成组件
form-create 是一个可以通过 JSON 生成具有动态渲染.数据收集.验证和提交功能的表单生成组件.支持2个UI框架,并且支持生成任何 Vue 组件.内置20种常用表单组件和自定义组件,再复杂 ...
- Vue+Element的动态表单,动态表格(后端发送配置,前端动态生成)
Vue+Element的动态表单,动态表格(后端发送配置,前端动态生成) 动态表单生成 ElementUI官网引导 Element表单生成 Element动态增减表单,在线代码 关键配置 templa ...
随机推荐
- Docker for Windows(五)实践搭建SqlServer服务&执行数据库操作
上一篇我们已经搭建了一个mysql数据库服务了:Docker for Windows(四)实践搭建&删除MySQL服务,发现用Docker确实是方便且容易,但上一篇主要是服务的搭建删除等基础操 ...
- ubuntu下使用python3的有些库时,解决"raise ImportError(str(msg) + ', please install the python3-tk package') ImportError: No module named '_tkinter', please install the python3-tk package"的错误
问题: 在Ubuntu下使用matplotlib这个库时,运行时出现如下错误: raise ImportError(str(msg) + ', please install the python3-t ...
- GDAL线面互转换(2)
在上一个文章中介绍了线转化为面和面转化为线,其主要的实现思路就是把面中的点取出来构成线,把线中的点取出来构成面,实际上就是一个硬拷贝,无奈客户的实际需求并非如此,客户想要线转面的时候几条相交线构成面, ...
- WPF ListView ListBox 常用的样式记录
ListView: <ListView x:Name="lvBlockedApps" ItemsSource="{Binding BlockedAppsCollec ...
- c# 从一个服务器 访问另外一个服务器上的文件
页面调用 function fnOpen(path) { window.open("~/FileHelp.ashx? url="); //window.open(url); } 后 ...
- PyQt4(简单界面)
import sys; from PyQt4 import QtCore, QtGui; app=QtGui.QApplication(sys.argv); widget=QtGui.QWidget( ...
- 4.Servlet过滤器
1.Servlet 编写过滤器 Servlet 过滤器是可用于 Servlet 编程的 Java 类,有以下目的: 在客户端的请求访问后端资源之前,拦截这些请求. 在服务器的响应发送回客户端之前,处理 ...
- Oracle诊断工具 - ORA-4030 Troubleshooting Tool
ORA-4030 说明Oracle服务器进程(server process)无法在操作系统(OS)上分配到足够的内存. 导致ORA-4030 的主要原因有: -物理内存不足 -OS kernel/ ...
- keyWindow与delegate中Window的区别
keyWindow与delegate中Window的区别 源码: // // ViewController.m // UIWindowRelated // // Created by YouXianM ...
- 用以替换系统NSLog的YouXianMingLog
用以替换系统NSLog的YouXianMingLog 这是本人自己使用并改良的用以替换系统NSLog的类,非常好用,以下是使用示例,现在开源出来并提供源码,好用的话顶一下吧^_^ 效果: YouXia ...