angular動(dòng)態(tài)表單制作
源碼:https://github.com/Karin001/ngx-dynamic-form

動(dòng)態(tài)表單使用場景
有時(shí)候我們需要一個(gè)靈活的表單,這個(gè)表單可以根據(jù)用戶的選擇,或者服務(wù)器返回的信息進(jìn)行重新配置,比如:增加或刪除一組input元素、一組select元素,等等。
在這樣的情況下,如果一開始就在模板里寫下所有的表單,利用一個(gè)ngif樹狀結(jié)構(gòu)進(jìn)行選擇控制,程序會(huì)變得比較冗余。
這時(shí)。程序最好是能夠根據(jù)用戶的選擇(driven by configuration)或者服務(wù)器的響應(yīng),自動(dòng)生成所需要的表單。這就是動(dòng)態(tài)表單要處理的業(yè)務(wù)。
組件生成的相關(guān)概念組件的兩個(gè)構(gòu)成
要?jiǎng)討B(tài)生成表單,需要先理解組件是如何生成的。
一個(gè)angular組件由兩部分所組成。
Wrapper
Wrapper能夠與組件進(jìn)行交互,當(dāng)一個(gè)Wrapper初始化完成后,就已經(jīng)幫我們實(shí)例化了一個(gè)組件。同時(shí),它也負(fù)責(zé)組件的change detection,以及觸發(fā)鉤子函數(shù)比如ngOnInit,ngOnChanges。
View
View負(fù)責(zé)呈現(xiàn)渲染過后的模板,將組件的外貌展示出來,并且能夠觸發(fā)Wrapper的change detection。一個(gè)組件可以有多個(gè)view,每一個(gè)view可以通過調(diào)用angular提供的兩個(gè)函數(shù)自行生成和銷毀,這個(gè)過程不用頂層的視圖參與。
組件的通常加載方式(非動(dòng)態(tài)加載方式)
通常情況下,我們都是把組件內(nèi)嵌到根組件或者另一個(gè)組件當(dāng)中使用。嵌入的組件稱為子組件,被嵌入的稱為父組件。這時(shí),當(dāng)我們的子組件代碼在被編譯時(shí),會(huì)生成一個(gè)組件工廠component factory(這是angular核心類ComponentFactory的一個(gè)實(shí)例),和一個(gè)hsot view,host view負(fù)責(zé)本組件在父組件視圖內(nèi)生成該組件的dom節(jié)點(diǎn),以及生成該組件的wrapper和view。
動(dòng)態(tài)加載組件
而當(dāng)我們想要將一個(gè)動(dòng)態(tài)組件插入某個(gè)組件視圖時(shí),則無法取得這個(gè)動(dòng)態(tài)組件的實(shí)例,因?yàn)檫@些是非動(dòng)態(tài)組件編譯器做的事。
實(shí)現(xiàn)動(dòng)態(tài)組件
angular提供了一些函數(shù)解決上面的難題,要使用這些函數(shù)我們需要注入兩個(gè)對(duì)象。
constructor(
private componentFactoryResolver: ComponentFactoryResolver,
private viewcontainerRef: ViewContainerRef,
) {
}
我們注入了ComponentFactoryResolver,和ViewContainerRef。
ComponentFactoryResolver上提供了一個(gè)方法(resolveComponentFactory()),該方法接收一個(gè)組件類作為參數(shù),生成一個(gè)基于該組件類的組件工廠,也就是我們之前提到的那個(gè)組件工廠。
ViewContainerRef提供了一個(gè)方法(createComponent()),該方法接收組件工廠作為參數(shù),在該視圖中生成子組件。(我個(gè)人的理解是它處理了host view所做的事,為組件生成了wrapper和view)
實(shí)現(xiàn)動(dòng)態(tài)表單
上文簡要的介紹了實(shí)現(xiàn)動(dòng)態(tài)組件的一些技術(shù),現(xiàn)在開始思考如何做一個(gè)動(dòng)態(tài)表單。
具體思路
我們想要做出一個(gè)獨(dú)立的動(dòng)態(tài)表單模塊,當(dāng)我們想要使用動(dòng)態(tài)表單時(shí),只需簡單引入這個(gè)模塊,稍加配置即可使用。
我們希望這個(gè)模塊做好了后,在頂層使用者的角度會(huì)是這樣一個(gè)工作流程:

我們可以很容易的做出一個(gè)具有輸入屬性的組件,問題的核心在于這個(gè)組件是如何根據(jù)輸入屬性生成我們想要的表單。
也就是說,是它自己調(diào)用ComponentFactoryResolver和ViewContainerRef進(jìn)行組件的動(dòng)態(tài)生成,還是交給別人處理。
下圖是實(shí)現(xiàn)思路:

實(shí)際上我們把動(dòng)態(tài)表單拆分成了一個(gè)個(gè)小的動(dòng)態(tài)組件(不預(yù)先加載),由外層的一個(gè)組件充當(dāng)一個(gè)容器,所有的動(dòng)態(tài)組件都會(huì)在里面進(jìn)行生成和銷毀,他們共同組成了一個(gè)動(dòng)態(tài)表單。調(diào)用ComponentFactoryResolver和ViewContainerRef生成組件的的這部分邏輯沒有集成在外層容器中,而是交給了一個(gè)自定義的指令和ng-container。因?yàn)橹噶顩]有視圖,他通過注入ViewContainerRef獲取到的是宿主的視圖容器。由于ng-container不會(huì)被渲染,所以獲取到的視圖容器就是外層組件容器的視圖容器。
這么處理的好處就是不需要由外層組件統(tǒng)一對(duì)各個(gè)拆分的動(dòng)態(tài)組件進(jìn)行管理,相當(dāng)于是由動(dòng)態(tài)組件自己進(jìn)行管理。
外層組件容器大概會(huì)是下面這樣:
<form> <ng-container *ngFor="let config of configs" [自定義指令] > </ng-container> </form>
configs是用戶的配置數(shù)據(jù),自定義指令寄宿在ng-container中,根據(jù)config渲染出各自的動(dòng)態(tài)組件,而ng-container是透明的。
看一下代碼目錄結(jié)構(gòu),最后會(huì)是這個(gè)樣子

以上就是大體的實(shí)現(xiàn)思路了,具體還有許多細(xì)節(jié)可以關(guān)注文章開頭提到的那兩篇文章,講的很詳細(xì)。
- 淺析Angular19 自定義表單控件
- Angular4編程之表單響應(yīng)功能示例
- Angular實(shí)現(xiàn)表單驗(yàn)證功能
- AngularJS 表單驗(yàn)證手機(jī)號(hào)的實(shí)例(非必填)
- Angular搜索 過濾 批量刪除 添加 表單驗(yàn)證功能集錦(實(shí)例代碼)
- AngularJS實(shí)現(xiàn)的獲取焦點(diǎn)及失去焦點(diǎn)時(shí)的表單驗(yàn)證功能示例
- AngularJS表單驗(yàn)證功能
- AngularJS實(shí)現(xiàn)注冊表單驗(yàn)證功能
- angular4中關(guān)于表單的校驗(yàn)示例
- AngularJS實(shí)現(xiàn)表單驗(yàn)證功能詳解
- AngularJS實(shí)現(xiàn)表單元素值綁定操作示例
- Angular將填入表單的數(shù)據(jù)渲染到表格的方法
- Angular4表單驗(yàn)證代碼詳解
相關(guān)文章
AngualrJS中每次$http請(qǐng)求時(shí)的一個(gè)遮罩層Directive
AngularJS是一款非常強(qiáng)大的前端MVC框架。接下來通過本文給大家介紹AngualrJS中每次$http請(qǐng)求時(shí)的一個(gè)遮罩層Directive,本文非常具有參考借鑒價(jià)值,特此分享供大家學(xué)習(xí)2016-01-01
快速學(xué)習(xí)AngularJs HTTP響應(yīng)攔截器
任何時(shí)候,如果我們想要為請(qǐng)求添加全局功能,例如身份認(rèn)證、錯(cuò)誤處理等,在請(qǐng)求發(fā)送給服務(wù)器之前或服務(wù)器返回時(shí)對(duì)其進(jìn)行攔截,是比較好的實(shí)現(xiàn)手段2015-12-12
使用AngularJS對(duì)表單提交內(nèi)容進(jìn)行驗(yàn)證的操作方法
AngularJS是一款優(yōu)秀的前端JS框架,已經(jīng)被用于Google的多款產(chǎn)品當(dāng)中。下面通過本文給大家分享使用AngularJS對(duì)表單提交內(nèi)容進(jìn)行驗(yàn)證的操作方法,需要的的朋友參考下吧2017-07-07
詳解在Angular4中使用ng2-baidu-map的方法
這篇文章主要介紹了在Angular4中使用ng2-baidu-map的方法,本文分步驟給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-06-06
angularjs實(shí)現(xiàn)對(duì)表單輸入改變的監(jiān)控(ng-change和watch兩種方式)
這篇文章主要介紹了angularjs通過ng-change和watch兩種方式實(shí)現(xiàn)對(duì)表單輸入改變的監(jiān)控,需要的朋友可以參考下2018-08-08
Angular 4.X開發(fā)實(shí)踐中的踩坑小結(jié)
這篇文章主要給大家介紹了關(guān)于Angular 4.X開發(fā)實(shí)踐中的一些踩坑經(jīng)驗(yàn),文中主要介紹的是使用ngIf或者ngSwitch出錯(cuò)以及多級(jí)依賴注入器的相關(guān)內(nèi)容,需要的朋友可以參考借鑒,下面來一起看看吧。2017-07-07
Angularjs 實(shí)現(xiàn)移動(dòng)端在線測評(píng)效果(推薦)
這篇文章主要介紹了Angularjs 實(shí)現(xiàn)移動(dòng)端在線測評(píng)效果,需要的朋友可以參考下2017-04-04

