![](/img/trans.png)
[英].setErrors is not a function, for FormControls in Angular
[英]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,這意味着一旦構建了表單就會調用它。 您可以在屏幕上看到整個FormGroup
是invalid
的,但所有單元格都是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.