@@ -194,54 +194,75 @@ 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- const existingMessages = new Set ( this . formErrors . map ( e => e . message ) ) ;
201-
202- errors
203- . filter ( ( error : FormError ) => ! existingMessages . has ( error . message ) )
204- . forEach ( ( error : FormError ) => {
205- const { fieldId } = error ;
206- const { fieldIndex } = error ;
207- let field : AbstractControl ;
208- if ( ! ! this . parentFormModel ) {
209- field = this . formBuilderService . getFormControlById ( fieldId , formGroup . parent as UntypedFormGroup , formModel , fieldIndex ) ;
210- } else {
211- field = this . formBuilderService . getFormControlById ( fieldId , formGroup , formModel , fieldIndex ) ;
212- }
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+ }
213211
214- if ( field ) {
215- const modelArrayIndex = fieldIndex > 0 ? fieldIndex : null ;
216- const model : DynamicFormControlModel = this . formBuilderService . findById ( fieldId , formModel , modelArrayIndex ) ;
217- this . formService . addErrorToField ( field , model , error . message ) ;
218- this . changeDetectorRef . detectChanges ( ) ;
219- }
220- } ) ;
221-
222- this . formErrors
223- . filter ( ( error : FormError ) => findIndex ( errors , {
224- fieldId : error . fieldId ,
225- fieldIndex : error . fieldIndex
226- } ) === - 1 )
227- . forEach ( ( error : FormError ) => {
228- const { fieldId } = error ;
229- const { fieldIndex } = error ;
230- let field : AbstractControl ;
231- if ( ! ! this . parentFormModel ) {
232- field = this . formBuilderService . getFormControlById ( fieldId , formGroup . parent as UntypedFormGroup , formModel , fieldIndex ) ;
233- } else {
234- 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 ) ;
235235 }
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+ console . log ( 'checking removal of' , key , prevMap . has ( key ) ) ;
252+ if ( ! nextMap . has ( key ) && prevMap . has ( key ) ) {
253+ const control = getControl ( prev ) ;
254+ if ( control ) {
255+ const model = getModel ( prev ) ;
256+ this . formService . removeErrorFromField ( control , model , prev . message ) ;
257+ this . formService . removeError ( this . formId , prev . fieldId , prev . fieldIndex ) ;
258+ removedErrors . push ( prev ) ;
259+ }
260+ }
261+ } ) ;
236262
237- if ( field ) {
238- const model : DynamicFormControlModel = this . formBuilderService . findById ( fieldId , formModel ) ;
239- this . formService . removeErrorFromField ( field , model , error . message ) ;
240- }
241- } ) ;
242- this . formErrors = errors ;
243- this . changeDetectorRef . detectChanges ( ) ;
244- } )
263+ this . formErrors = this . formErrors . filter ( error => ! removedErrors . includes ( error ) ) ;
264+ this . changeDetectorRef . detectChanges ( ) ;
265+ } ) ,
245266 ) ;
246267 }
247268
0 commit comments