@energycap/components 0.39.21-ECAP-25650-file-upload-validation-support.20240806-1029 → 0.39.21-ECAP-25650-file-upload-validation-support.20240806-1611

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4106,7 +4106,9 @@ const FileTypeExtensions = {
4106
4106
  };
4107
4107
  class FileUploadComponent extends FormControlBase {
4108
4108
  // static class to create the form group from a parent component
4109
- static getFormModel(validators, disabled = false, fileValidators) {
4109
+ static getFormModel(validators, disabled = false,
4110
+ /** Any validators required to make sure the selected file is valid. It is recommended that you use `FileUploadComponent.getFileValidator` to help construct the validator(s). NOTE: This currently only works when multiSelect is false. */
4111
+ fileValidators) {
4110
4112
  let formGroup = new FormGroup({
4111
4113
  file: new FormControl({ value: null, disabled: disabled }, { validators: validators, asyncValidators: fileValidators }),
4112
4114
  name: new FormControl({ value: null, disabled: disabled }, validators),
@@ -4118,10 +4120,18 @@ class FileUploadComponent extends FormControlBase {
4118
4120
  }
4119
4121
  return formGroup;
4120
4122
  }
4123
+ /**
4124
+ * Helper function that returns an async validator to be used with the file upload control.
4125
+ * This is useful for when the file needs to be validated before it can be uploaded.
4126
+ *
4127
+ * @param callback The callback function that will be called to validate the file. Parameters for the callback are the file and the base64 string for the file.
4128
+ * base64 is null if the fileOutput input on the FileUploadComponent is set to raw. Using fileOutput set to base64 is recommended for images.
4129
+ */
4121
4130
  static getFileValidator(callback) {
4122
4131
  return async (control) => {
4123
4132
  if (control.value && control.parent) {
4124
4133
  let file = control.value;
4134
+ // For images, we need the base64 string to validate image dimensions
4125
4135
  let base64 = control.parent.get('base64FileString')?.value;
4126
4136
  return await callback(file, base64);
4127
4137
  }
@@ -4173,7 +4183,8 @@ class FileUploadComponent extends FormControlBase {
4173
4183
  });
4174
4184
  }
4175
4185
  });
4176
- // Sync errors from the file control to the name control whenever the file control status changes
4186
+ // Sync errors from the file control to the name control whenever the file control status changes.
4187
+ // The name control is the only one displayed to the user so we need to show the errors there.
4177
4188
  this.formModel.get('file')?.statusChanges.pipe(takeUntil(this.componentDestroyed)).subscribe(() => {
4178
4189
  const errors = this.formModel.get('file')?.errors ?? null;
4179
4190
  this.formModel.get('name')?.setErrors(errors);
@@ -4218,26 +4229,47 @@ class FileUploadComponent extends FormControlBase {
4218
4229
  * @param file
4219
4230
  * @param base64FileString Optional: Will have a value provided if the fileOutput is set to base64
4220
4231
  */
4221
- async processFile(file, base64FileString) {
4232
+ async processFile(file, base64FileString = null) {
4233
+ // If we have async validators on the file control we need to do validation before we trigger the upload
4234
+ const validateBeforeUpload = !!this.formModel.controls.file.asyncValidator;
4235
+ if (validateBeforeUpload) {
4236
+ await this.validateFile(file, base64FileString);
4237
+ }
4238
+ if (this.onFileSelected) {
4239
+ // Only call the onFileSelected callback to upload the file if the form group is valid
4240
+ if (this.formModel.valid) {
4241
+ try {
4242
+ let result = await this.onFileSelected(file);
4243
+ // If we did validation, just patch the form result because the file is already in the form
4244
+ if (validateBeforeUpload) {
4245
+ this.formModel.patchValue({ uploadResult: result ?? null });
4246
+ }
4247
+ else {
4248
+ this.formModel.patchValue({ base64FileString, file, name: file.name, uploadResult: result ?? null });
4249
+ }
4250
+ }
4251
+ catch (e) {
4252
+ // Bummer, we're not going to do anything about it though.
4253
+ // We are not patching any of the result so any existing information remains
4254
+ }
4255
+ }
4256
+ // If we don't have an onFileSelected callback we just patch the form model.
4257
+ // In the case of pre-upload validation the form already has the file so we don't want to patch again.
4258
+ }
4259
+ else if (!validateBeforeUpload) {
4260
+ this.formModel.patchValue({ base64FileString, file, name: file.name, uploadResult: null });
4261
+ }
4262
+ }
4263
+ /** Patches the form with the selected file in order to trigger control validation */
4264
+ async validateFile(file, base64FileString = null) {
4222
4265
  // Patch the file first to trigger any file validators
4223
- this.patchProcessedFile(file, base64FileString);
4266
+ this.formModel.patchValue({ base64FileString, file, name: file.name, uploadResult: null });
4224
4267
  // If we have any async validators pending we need to wait for them to complete before we know if the form is valid
4225
4268
  if (this.formModel.pending) {
4226
4269
  await this.formModel.statusChanges.pipe(filter(status => status !== 'PENDING'), take(1), takeUntil(this.componentDestroyed)).toPromise();
4227
4270
  }
4228
4271
  // Mark the name control as touched so that any validation errors will show
4229
4272
  this.formModel.controls.name.markAsTouched();
4230
- // Only call the onFileSelected callback to upload the file if the form is valid
4231
- if (this.onFileSelected && this.formModel.valid) {
4232
- try {
4233
- let result = await this.onFileSelected(file);
4234
- this.formModel.patchValue({ uploadResult: result ?? null });
4235
- }
4236
- catch (e) {
4237
- // Bummer, we're not going to do anything about it though.
4238
- // We are not patching any of the result so any existing information remains
4239
- }
4240
- }
4241
4273
  }
4242
4274
  /**
4243
4275
  * Based on the fileOutput return whether this component is expected to deliver a base64 output
@@ -4246,21 +4278,6 @@ class FileUploadComponent extends FormControlBase {
4246
4278
  isBase64FileOutput() {
4247
4279
  return this.fileOutput === 'base64';
4248
4280
  }
4249
- /**
4250
- * When the file was selected and processed patch the file information that the hosting form will
4251
- * be looking for.
4252
- * @param file
4253
- * @param base64FileString
4254
- * @param onFileSelectedResult
4255
- */
4256
- patchProcessedFile(file, base64FileString) {
4257
- this.formModel?.patchValue({
4258
- file: file,
4259
- name: file?.name,
4260
- base64FileString: base64FileString ?? null,
4261
- uploadResult: null
4262
- });
4263
- }
4264
4281
  /** Maps the files to an array of File objects and sends them along
4265
4282
  * to the derived onMultipleFileSelected method in the hosting component
4266
4283
  */