Skip to content

Commit 0586de1

Browse files
committed
LIBDRUM-909. Force re-display of validation errors on page refresh
These changes are an attempt to fix an apparent race condition between the Angular field validation and the DSpace refresh of the page on attempted submission. The issue being fixed is that the GUI validation error warnings momentarily "flash" and then disappear when submitting the form using the "Deposit" button. The workflow appears to be: * The user does not focus on or enter anything in a required field, and then attempts to submit the form. * The request to the DSpace backend does not include any JSON related to the required field * A 200 response is returned from the DSpace backend, with an "errors" array in the JSON, indicating the validation error * The 200 response triggers a page refresh, which wipes out any existing validation error display on the page. This change forces all the validation errors to be re-displayed by touching the relevant fields and triggering a validity check after the page is refreshed. It is unclear whether this is the optimal fix, so it has not been submitted upstream to DSpace. Also, DSpace has been working on various fixes, so the changes in this class should be re-evaluated on upgrades, and removed if possible. https://umd-dit.atlassian.net/browse/LIBDRUM-909
1 parent 5388c7b commit 0586de1

File tree

2 files changed

+86
-1
lines changed

2 files changed

+86
-1
lines changed

docs/DrumAngularCustomizations.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,21 @@ would successfully complete:
8080

8181
* Commented out the "codecov" job, because UMD does not have an appropriate key
8282
for uploading the results to codecov.io.
83+
84+
## Change to Submission Form Validation Handling
85+
86+
The "SubmissionSectionFormComponent" class
87+
(src/app/submission/sections/form/section-form.component.ts) has been
88+
modified with a "ngAfterViewChecked" method to ensure that form validation
89+
errors are displayed, even after a page refresh.
90+
91+
This change is intended to fix an issue (see LIBDRUM-909) in which submitting
92+
a form without all the required fields populated would not show GUI validation
93+
warnings on all affected fields. This is apparently caused by a race condition
94+
between the Angular validation handling, and a page refresh triggered by the
95+
DSpace backend response.
96+
97+
It is unclear whether this is the optimal fix, so it has not been submitted
98+
upstream to DSpace. Also, DSpace has been working on various similar fixes, so
99+
the changes in this class should be re-evaluated on upgrades, and
100+
removed if possible.

src/app/submission/sections/form/section-form.component.ts

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { NgIf } from '@angular/common';
22
import {
3+
AfterViewChecked,
34
ChangeDetectorRef,
45
Component,
56
Inject,
@@ -24,6 +25,7 @@ import {
2425
map,
2526
mergeMap,
2627
take,
28+
takeUntil,
2729
tap,
2830
} from 'rxjs/operators';
2931

@@ -82,7 +84,16 @@ import { SectionFormOperationsService } from './section-form-operations.service'
8284
],
8385
standalone: true,
8486
})
85-
export class SubmissionSectionFormComponent extends SectionModelComponent {
87+
// UMD Customization
88+
// This class is customized to correct an issue seem with the display of
89+
// validation errors (see LIBDRUM-909).
90+
//
91+
// It is unclear whether this is the optimal fix, so it has not been submitted
92+
// upstream to DSpace. Also, DSpace has been working on various fixes, so
93+
// the changes in this class should be re-evaluated on upgrades, and
94+
// removed if possible.
95+
export class SubmissionSectionFormComponent extends SectionModelComponent implements AfterViewChecked {
96+
// End UMD Customization
8697

8798
/**
8899
* The form id
@@ -157,6 +168,11 @@ export class SubmissionSectionFormComponent extends SectionModelComponent {
157168
*/
158169
protected isSectionReadonly = false;
159170

171+
// UMD Customization
172+
private triggerValidationErrorDisplay = false;
173+
private pendingErrors: SubmissionSectionError[] = [];
174+
// End UMD Customization
175+
160176
/**
161177
* The FormComponent reference
162178
*/
@@ -231,7 +247,58 @@ export class SubmissionSectionFormComponent extends SectionModelComponent {
231247
this.cdr.detectChanges();
232248
}
233249
});
250+
251+
252+
// UMD Customization
253+
// Logic to maintain red borders after an attempted deposit
254+
const sectionErrors = this.sectionService.getSectionErrors(this.submissionId, this.sectionData.id);
255+
if (sectionErrors) {
256+
sectionErrors.pipe(
257+
filter((errors: SubmissionSectionError[]) => errors && errors.length > 0),
258+
takeUntil(this.subs),
259+
).subscribe((errors: SubmissionSectionError[]) => {
260+
// Store errors and raise flag indicating validation errors should be
261+
// displayed.
262+
this.pendingErrors = errors;
263+
this.triggerValidationErrorDisplay = true;
264+
});
265+
}
266+
// End UMD Customization
267+
}
268+
269+
// UMD Customization
270+
ngAfterViewChecked() {
271+
if (this.triggerValidationErrorDisplay && this.formRef && this.formRef.formGroup) {
272+
// Lower the flag immediately to prevent infinite loops
273+
this.triggerValidationErrorDisplay = false;
274+
let touchedAny = false;
275+
this.pendingErrors.forEach((error: SubmissionSectionError) => {
276+
// Paths have the form /sections/mhheaDescribe/dc.title
277+
const pathParts = error.path.split('/');
278+
const fieldId = pathParts[pathParts.length - 1];
279+
const formGroup = this.formRef.formGroup;
280+
281+
if (formGroup) {
282+
// Retrieve the specific control from the Reactive Form
283+
const normalizedFieldId = fieldId.replace(/\./g, '_');
284+
const control = this.formBuilderService.getFormControlById(normalizedFieldId, formGroup, this.formModel);
285+
286+
if (control) {
287+
// markAsTouched() triggers the 'is-invalid' class/red border
288+
control.markAsTouched();
289+
// Optional: markAsDirty() ensures Angular treats the field as modified
290+
control.markAsDirty();
291+
control.updateValueAndValidity();
292+
touchedAny = true;
293+
}
294+
}
295+
});
296+
if (touchedAny) {
297+
this.cdr.detectChanges();
298+
}
299+
}
234300
}
301+
// End UMD Customization
235302

236303
/**
237304
* Unsubscribe from all subscriptions

0 commit comments

Comments
 (0)