簡體   English   中英

Angular Reactive Form - 使用 OnPush 時,setErrors 不更新 FormArray 內 FormControls 的視圖

[英]Angular Reactive Form - setErrors not updating view for FormControls inside FormArray when OnPush is used

這是一個有趣的行為,我在多個項目中嘗試過,並放棄了將 OnPush 用於 FormArray,更具體地說,它是FormGrop 的一行包含 FormControl 但是,我認為是時候在這里提出一個問題,以便其他人也可能遇到同樣的問題(或者只是我太愚蠢而忘記了一行簡單的代碼,如果是的話請指出,謝謝),我在這里創建了一個模型: 堆棧閃電戰

出於某種原因,我的項目對所有此類虛擬組件使用OnPush ,如果需要視圖更新,則需要手動調用ChangeDetectionRef.markForCheck 但是這次無論我把標記放在哪里,它都沒有顯示出任何差異。

通常,我創建了一個save$ Subject 來即時進行驗證,如果valid ,則將整個 Grid保存到某個地方。 現在,由於save$是一個 BehaviourSubject,這意味着一旦構建了表單就會調用它。 您可以在屏幕上看到整個FormGroupinvalid的,但所有單元格都是valid的,這很奇怪。 在此處輸入圖像描述

我提到“非 onpush”的原因是因為在這種模式下,Angular 會為你運行 CD。 如果您的代碼在默認模式下按預期工作,則意味着您的“onpush”代碼只需要觸發 CD。
我並不是要告訴您應該切換到默認模式。

為什么它在您的原始問題中不起作用:
表單本身,默認情況下在初始化后運行updateValueAndValidity ,您不聲明任何驗證器 => 表單狀態有效; 然后你在幕后調用 setErrors,將 from status 設置為 false => 這會導致視圖不一致,因此會出現 ng100 錯誤。

//編輯:
我再次調試流程,發現每個控件添加到窗體后,它都會再次運行 updateValueAndValidity 函數。 這意味着,setErrors 將首先導致表單無效,然后 updateValueAndValidity 將使它再次有效。 不一致仍然存在,只是反過來。
//結束編輯

骯臟的 hack 是使用 setTimeout,我個人不喜歡也不推薦。 但是要給出一個合適的解決方案,就需要了解代碼中的業務邏輯。

這是我在評論中發布的代碼。

setTimeout(() => {
        control.setErrors(Object.keys(errors).length ? errors : null);        
});

這有助於安排 setError(實際上是有效狀態)在下一輪 CD 中運行。
此代碼還沒有任何 CD。 所以是的,表格始終有效 => 這就是我告訴您創建一個按鈕來查看 CD 的原因。

現在我們不希望用戶點擊一個新按鈕來查看表單更新。 我們需要在代碼中運行 CD。 那么放在哪里呢?
我們知道 setError 會觸發表單狀態,所以我們稍后會安排它,setError 在哪里被調用? customValidator ,我們將安排此功能稍后運行,因此最終要修改的代碼在這里:

//instead of run setTimeout in a loop
//we make sure that all setError is scheduled in one run
setTimeout(() => {
      customValidator()(form);
      this.cd.markForCheck();
    })

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM