@@ -194,55 +194,74 @@ export class FormComponent implements OnDestroy, OnInit {
194194 this . formService . getForm ( this . formId ) . pipe (
195195 filter ( ( formState : FormEntry ) => ! ! formState && ( isNotEmpty ( formState . errors ) || isNotEmpty ( this . formErrors ) ) ) ,
196196 map ( ( formState ) => formState . errors ) ,
197- distinctUntilChanged ( ) )
198- . subscribe ( ( errors : FormError [ ] ) => {
199- const { formGroup, formModel } = this ;
200- errors
201- . filter ( ( error : FormError ) => findIndex ( this . formErrors , {
202- fieldId : error . fieldId ,
203- fieldIndex : error . fieldIndex
204- } ) === - 1 )
205- . forEach ( ( error : FormError ) => {
206- const { fieldId } = error ;
207- const { fieldIndex } = error ;
208- let field : AbstractControl ;
209- if ( ! ! this . parentFormModel ) {
210- field = this . formBuilderService . getFormControlById ( fieldId , formGroup . parent as UntypedFormGroup , formModel , fieldIndex ) ;
211- } else {
212- field = this . formBuilderService . getFormControlById ( fieldId , formGroup , formModel , fieldIndex ) ;
213- }
197+ distinctUntilChanged ( ) ,
198+ ) . subscribe ( ( errors : FormError [ ] ) => {
199+ const { formGroup, formModel } = this ;
200+
201+ const prevMap = new Map < string , FormError > (
202+ this . formErrors . map ( e => [ `${ e . fieldId } :${ e . fieldIndex } ` , e ] ) ,
203+ ) ;
204+ const nextMap = new Map < string , FormError > (
205+ errors . map ( e => [ `${ e . fieldId } :${ e . fieldIndex } ` , e ] ) ,
206+ ) ;
207+
208+ if ( isEqual ( prevMap , nextMap ) ) {
209+ return ;
210+ }
214211
215- if ( field ) {
216- const modelArrayIndex = fieldIndex > 0 ? fieldIndex : null ;
217- const model : DynamicFormControlModel = this . formBuilderService . findById ( fieldId , formModel , modelArrayIndex ) ;
218- this . formService . addErrorToField ( field , model , error . message ) ;
219- this . changeDetectorRef . detectChanges ( ) ;
220- }
221- } ) ;
222-
223- this . formErrors
224- . filter ( ( error : FormError ) => findIndex ( errors , {
225- fieldId : error . fieldId ,
226- fieldIndex : error . fieldIndex
227- } ) === - 1 )
228- . forEach ( ( error : FormError ) => {
229- const { fieldId } = error ;
230- const { fieldIndex } = error ;
231- let field : AbstractControl ;
232- if ( ! ! this . parentFormModel ) {
233- field = this . formBuilderService . getFormControlById ( fieldId , formGroup . parent as UntypedFormGroup , formModel , fieldIndex ) ;
234- } else {
235- field = this . formBuilderService . getFormControlById ( fieldId , formGroup , formModel , fieldIndex ) ;
212+ const getControl = ( err : FormError ) : AbstractControl | null => {
213+ return this . parentFormModel
214+ ? this . formBuilderService . getFormControlById ( err . fieldId , formGroup . parent as UntypedFormGroup , formModel , err . fieldIndex )
215+ : this . formBuilderService . getFormControlById ( err . fieldId , formGroup , formModel , err . fieldIndex ) ;
216+ } ;
217+
218+ const getModel = ( err : FormError ) : DynamicFormControlModel => {
219+ const modelArrayIndex = err . fieldIndex > 0 ? err . fieldIndex : null ;
220+ return this . formBuilderService . findById ( err . fieldId , formModel , modelArrayIndex ) ;
221+ } ;
222+ // Add or change (including revert) errors
223+ errors . forEach ( next => {
224+ const key = `${ next . fieldId } :${ next . fieldIndex } ` ;
225+ const prev = prevMap . get ( key ) ;
226+ if ( ! prev || prev . message !== next . message ) {
227+ // Remove old message if changed
228+ if ( prev ) {
229+ const prevControl = getControl ( prev ) ;
230+ if ( prevControl ) {
231+ const prevModel = getModel ( prev ) ;
232+ this . formService . removeErrorFromField ( prevControl , prevModel , prev . message ) ;
233+ this . formService . removeError ( this . formId , prev . fieldId , prev . fieldIndex ) ;
234+ this . formErrors . splice ( findIndex ( this . formErrors , prev ) , 1 ) ;
236235 }
236+ }
237+ // Add new message
238+ const control = getControl ( next ) ;
239+ if ( control ) {
240+ const model = getModel ( next ) ;
241+ this . formService . addErrorToField ( control , model , next . message ) ;
242+ this . formErrors . push ( next ) ;
243+ }
244+ }
245+ } ) ;
246+
247+ const removedErrors : FormError [ ] = [ ] ;
248+ // Remove errors for fields no longer present
249+ this . formErrors . forEach ( prev => {
250+ const key = `${ prev . fieldId } :${ prev . fieldIndex } ` ;
251+ if ( ! nextMap . has ( key ) && prevMap . has ( key ) ) {
252+ const control = getControl ( prev ) ;
253+ if ( control ) {
254+ const model = getModel ( prev ) ;
255+ this . formService . removeErrorFromField ( control , model , prev . message ) ;
256+ this . formService . removeError ( this . formId , prev . fieldId , prev . fieldIndex ) ;
257+ removedErrors . push ( prev ) ;
258+ }
259+ }
260+ } ) ;
237261
238- if ( field ) {
239- const model : DynamicFormControlModel = this . formBuilderService . findById ( fieldId , formModel ) ;
240- this . formService . removeErrorFromField ( field , model , error . message ) ;
241- }
242- } ) ;
243- this . formErrors = errors ;
244- this . changeDetectorRef . detectChanges ( ) ;
245- } )
262+ this . formErrors = this . formErrors . filter ( error => ! removedErrors . includes ( error ) ) ;
263+ this . changeDetectorRef . detectChanges ( ) ;
264+ } ) ,
246265 ) ;
247266 }
248267
0 commit comments