關於動態表單遇到的一些問題

小強Zzz發表於2022-03-29

前言

一個demo應用到專案上的時候總會出現各種各樣的問題。

版本問題

image.png
在編寫專案時,照著前幾天的實驗demo寫,viemContainerRef.createComponent<A>(B),B是A介面的實現類,但是在這裡B卻報錯了,一開始沒仔細看報錯詳細資訊,以為是B對A的繼承關係有問題,但是檢查了後並沒有錯。去網上找了一番後也沒有發現解決辦法。然後我去檢視原始碼,
image.png
發現方法引數需要一個工廠類而不是一個子類,感到了疑惑,怎麼demo裡沒問題呢。又去demo裡看了一下原始碼。
image.png
發現引數型別並不相同,發現是angular版本問題,專案用的是angular12版本,而demo用的是angular13版本。最終原因是版本問題造成的。
去谷歌viemContainerRef.createComponent()的使用例項,網上還是老版本的使用,照著寫上

constructor(private resolver: ComponentFactoryResolver) {}

loadComponent() {
    
  const factory: ComponentFactory<FormItemTypeComponent> = this.resolver.resolveComponentFactory(FormItemTextComponent);

  const viewContainerRef = this.formItem.viewContainerRef;

  const componentRef = viewContainerRef.createComponent(factory);
  componentRef.instance.formItem = formItem;
}

後來又去了的老版本的angular官網,也發現了類似的寫法。

引用問題

@ViewChild(FormItemDirective, {static: true})
formItem!: FormItemDirective;

loadComponent() {
for (var i = 0; i < this.task.formItems.length; i++) {
  const formItem = this.task.formItems[i];

  console.log(this.formItem);

  const factory: ComponentFactory<FormItemTypeComponent> =
    this.resolver.resolveComponentFactory(FormItemTextComponent);

  const viewContainerRef = this.formItem.viewContainerRef;

  const componentRef = viewContainerRef.createComponent(factory);
  componentRef.instance.formItem = formItem;
}

image.png
遇到一個undefined問題,此時的formItem是使用@ViewChild註解注入進來的,這個也沒有什麼報錯資訊,只能猜了。為了防止版本問題,我也檢視了12版本的官方程式碼和原始碼,並沒有什麼問題。
官方例項裡指令跟元件在一個模組裡,沒有通過@ViewChild註解注入進來,猜測可能是由於沒有引入指令,而指令跟元件在不同的模組裡,我嘗試將兩者放入同意模組已排除不是引用的錯誤,也沒有解決問題。
一時沒有了思路,在宇軒同學的幫助下,找到了問題所在。
解決辦法是將ViewModule引入TaskModule中,ViewModule是指令所在元件的所在模組,TaskModule是大功能模組的總模組。

├── add
├── directive
├── edit
├── form-item-type
├── index
├── item-add
├── item-edit
├── item-view
├── task-routing.module.ts
├── task.module.ts
└── view

但是為什麼改這個就可以了,我倆都沒有想明白。

其他一些問題

在動態表單裡,後臺返回的表單項陣列必然不可能存入一個元件進去,而前臺需要每個表單項型別所對應元件動態載入,如果單純的寫if語句進行挨個判斷,使用動態表單又成了無用功,想到可以使用HashMap資料結構,將表單項型別與對應元件儲存起來,用的時候獲取表單項型別所對應元件。
表單傳值也是一個問題,不同於傳統的v層將每個標單項羅列在一起。想法是通過將每個表單值先傳到m層,當提交的時候統一傳送給後臺。
感謝宇軒同學提供的幫助。

相關文章