本文主要和大家介紹angular動態表單的實作思路。具體實現細節可以參考社群裡semlinker的動態創建表單這篇文章,以及他推薦的參考資源 Configurable Reactive Forms in Angular with dynamic components,筆者這篇文章主要是以上文章的部分翻譯和思考。
#有時候我們需要一個靈活的表單,這個表單可以根據使用者的選擇,或是伺服器傳回的資訊進行重新配置,例如:增加或刪除一組input元素、一組select元素,等等。
在這樣的情況下,如果一開始就在模板裡寫下所有的表單,利用一個ngif樹狀結構進行選擇控制,程式會變得比較冗餘。
這時。程式最好是能夠根據使用者的選擇(driven by configuration)或伺服器的回應,自動產生所需的表單。這就是動態表單要處理的業務。
要動態產生表單,需要先理解組件是如何產生的。
一個angular元件由兩個部分所組成。
Wrapper
Wrapper能夠與元件進行交互,當一個Wrapper初始化完成後,就已經幫我們實例化了一個組件。同時,它也負責組件的change detection,以及觸發鉤子函數例如ngOnInit,ngOnChanges。
View
#View負責呈現渲染過後的模板,將元件的外觀展示出來,並且能夠觸發Wrapper的change detection。一個元件可以有多個view,每一個view可以透過呼叫angular提供的兩個函數自行產生和銷毀,這個過程不用頂層的視圖參與。
#通常情況下,我們都是把元件內嵌到根元件或另一個組件當中使用。嵌入的元件稱為子元件,被嵌入的稱為父元件。這時,當我們的子元件程式碼在被編譯時,會產生一個元件工廠component factory(這是angular核心類別ComponentFactory的一個實例),和一個hsot view, host view負責本元件在父元件視圖內產生該元件的dom節點,以及產生該元件的wrapper和view。
而當我們想要將一個動態元件插入某個元件視圖時,則無法取得這個動態元件的實例,因為這些是非動態元件編譯器所做的事。
angular提供了一些函數來解決上面的難題,要使用這些函數我們需要注入兩個物件。
constructor( private componentFactoryResolver: ComponentFactoryResolver, private viewcontainerRef: ViewContainerRef, ) { }
我們注入了ComponentFactoryResolver,和ViewContainerRef。
ComponentFactoryResolver上提供了一個方法(resolveComponentFactory()),該方法接收一個元件類別作為參數,產生一個基於該元件類別的元件工廠,也就是我們之前提到的那個組件工廠。
ViewContainerRef提供了一個方法(createComponent()),該方法接收元件工廠作為參數,在該視圖中產生子元件。 (我個人的理解是它處理了host view所做的事,為元件生成了wrapper和view)
上文簡要的介紹了實作動態組件的一些技術,現在開始思考如何做一個動態表單。
我們想要做出一個獨立的動態表單模組,當我們想要使用動態表單時,只需簡單引入這個模組,稍加配置即可使用。
我們希望這個模組做好了後,在頂層使用者的角度會是這樣一個工作流程:
我們可以很容易的做出一個具有輸入屬性的元件,問題的核心在於這個元件是如何根據輸入屬性產生我們想要的表單。
也就是說,是它自己呼叫ComponentFactoryResolver和ViewContainerRef進行元件的動態生成,還是交給別人處理。
下圖是實作想法:
#其實我們把動態表單分割成一個個小的動態元件(不預先載入),由外層的一個元件充當一個容器,所有的動態元件都會在裡面進行產生和銷毀,他們共同組成了一個動態表單。
调用ComponentFactoryResolver和ViewContainerRef生成组件的的这部分逻辑没有集成在外层容器中,而是交给了一个自定义的指令和ng-container。因为指令没有视图,他通过注入ViewContainerRef获取到的是宿主的视图容器。由于ng-container不会被渲染,所以获取到的视图容器就是外层组件容器的视图容器。
这么处理的好处就是不需要由外层组件统一对各个拆分的动态组件进行管理,相当于是由动态组件自己进行管理。
外层组件容器大概会是下面这样:
<form> <ng-container *ngFor="let config of configs" [自定义指令] > </ng-container> </form>
configs是用户的配置数据,自定义指令寄宿在ng-container中,根据config渲染出各自的动态组件,而ng-container是透明的。
看一下代码目录结构,最后会是这个样子
以上就是大体的实现思路了,具体还有许多细节可以关注文章开头提到的那两篇文章,讲的很详细。
相关推荐:
jQuery实现动态表单验证时文本框抖动效果完整实例_jquery
以上是angular動態表單實例講解的詳細內容。更多資訊請關注PHP中文網其他相關文章!