@energycap/components 0.39.20 → 0.39.21-ECAP-25650-file-upload-validation-support.20240805-1645
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.
- package/esm2020/lib/controls/file-upload/file-upload.component.mjs +38 -26
- package/esm2020/lib/core/validation-message.service.mjs +4 -1
- package/esm2020/lib/shared/page/page-base/page-base.component.mjs +7 -3
- package/fesm2015/energycap-components.mjs +44 -24
- package/fesm2015/energycap-components.mjs.map +1 -1
- package/fesm2020/energycap-components.mjs +43 -24
- package/fesm2020/energycap-components.mjs.map +1 -1
- package/lib/controls/file-upload/file-upload.component.d.ts +15 -4
- package/lib/shared/page/page-base/page-base.component.d.ts +2 -2
- package/package.json +1 -1
- package/src/assets/locales/en_US.json +2 -1
@@ -7,7 +7,7 @@ import { DOCUMENT, CommonModule } from '@angular/common';
|
|
7
7
|
import * as i0 from '@angular/core';
|
8
8
|
import { Injectable, EventEmitter, Component, HostBinding, Input, Output, ViewChild, Directive, Host, Pipe, HostListener, Inject, ElementRef, ViewEncapsulation, ContentChild, TemplateRef, ViewContainerRef, ContentChildren, NgModule, Injector } from '@angular/core';
|
9
9
|
import * as i4 from '@angular/forms';
|
10
|
-
import { Validators, UntypedFormControl, FormControlDirective, UntypedFormGroup, UntypedFormArray, FormsModule, ReactiveFormsModule } from '@angular/forms';
|
10
|
+
import { Validators, UntypedFormControl, FormControlDirective, UntypedFormGroup, UntypedFormArray, FormGroup, FormControl, FormsModule, ReactiveFormsModule } from '@angular/forms';
|
11
11
|
import * as i1$2 from '@angular/router';
|
12
12
|
import { NavigationEnd, convertToParamMap, NavigationStart, Router, RouterModule, ActivatedRoute } from '@angular/router';
|
13
13
|
import * as i2 from '@ngx-translate/core';
|
@@ -738,6 +738,9 @@ class ValidationMessageService {
|
|
738
738
|
case 'domain':
|
739
739
|
translationObservables.push(this.translate.get('DomainValidationMessage_SC'));
|
740
740
|
break;
|
741
|
+
case 'invalidFile':
|
742
|
+
translationObservables.push(this.translate.get('is invalid'));
|
743
|
+
break;
|
741
744
|
default:
|
742
745
|
break;
|
743
746
|
}
|
@@ -4132,18 +4135,29 @@ const FileTypeExtensions = {
|
|
4132
4135
|
};
|
4133
4136
|
class FileUploadComponent extends FormControlBase {
|
4134
4137
|
// static class to create the form group from a parent component
|
4135
|
-
static getFormModel(validators, disabled = false) {
|
4136
|
-
let formGroup = new
|
4137
|
-
file: new
|
4138
|
-
name: new
|
4139
|
-
base64FileString: new
|
4140
|
-
uploadResult: new
|
4138
|
+
static getFormModel(validators, disabled = false, fileValidators) {
|
4139
|
+
let formGroup = new FormGroup({
|
4140
|
+
file: new FormControl({ value: null, disabled: disabled }, validators),
|
4141
|
+
name: new FormControl({ value: null, disabled: disabled }, { validators: validators, asyncValidators: fileValidators }),
|
4142
|
+
base64FileString: new FormControl(null),
|
4143
|
+
uploadResult: new FormControl(null),
|
4141
4144
|
});
|
4142
4145
|
if (disabled) {
|
4143
4146
|
formGroup.disable();
|
4144
4147
|
}
|
4145
4148
|
return formGroup;
|
4146
4149
|
}
|
4150
|
+
static getFileValidator(callback) {
|
4151
|
+
return (nameControl) => __awaiter(this, void 0, void 0, function* () {
|
4152
|
+
var _a, _b, _c;
|
4153
|
+
if (nameControl.value && nameControl.parent && ((_a = nameControl.parent.get('file')) === null || _a === void 0 ? void 0 : _a.value)) {
|
4154
|
+
let file = (_b = nameControl.parent.get('file')) === null || _b === void 0 ? void 0 : _b.value;
|
4155
|
+
let base64 = (_c = nameControl.parent.get('base64FileString')) === null || _c === void 0 ? void 0 : _c.value;
|
4156
|
+
return yield callback(file, base64);
|
4157
|
+
}
|
4158
|
+
return null;
|
4159
|
+
});
|
4160
|
+
}
|
4147
4161
|
constructor(validationMessageService, formGroupHelper) {
|
4148
4162
|
super(validationMessageService, formGroupHelper);
|
4149
4163
|
this.validationMessageService = validationMessageService;
|
@@ -4185,7 +4199,6 @@ class FileUploadComponent extends FormControlBase {
|
|
4185
4199
|
if (!value) {
|
4186
4200
|
this.formModel.patchValue({
|
4187
4201
|
file: null,
|
4188
|
-
name: null,
|
4189
4202
|
base64FileString: null,
|
4190
4203
|
uploadResult: null
|
4191
4204
|
});
|
@@ -4235,19 +4248,25 @@ class FileUploadComponent extends FormControlBase {
|
|
4235
4248
|
*/
|
4236
4249
|
processFile(file, base64FileString) {
|
4237
4250
|
return __awaiter(this, void 0, void 0, function* () {
|
4238
|
-
|
4251
|
+
// Patch the file first to trigger any file validators
|
4252
|
+
this.patchProcessedFile(file, base64FileString);
|
4253
|
+
// If we have any async validators pending we need to wait for them to complete before we know if the form is valid
|
4254
|
+
if (this.formModel.pending) {
|
4255
|
+
yield this.formModel.statusChanges.pipe(filter(status => status !== 'PENDING'), take(1), takeUntil(this.componentDestroyed)).toPromise();
|
4256
|
+
}
|
4257
|
+
// Mark the name control as touched so that any validation errors will show
|
4258
|
+
this.formModel.controls.name.markAsTouched();
|
4259
|
+
// Only call the onFileSelected callback to upload the file if the form is valid
|
4260
|
+
if (this.onFileSelected && this.formModel.valid) {
|
4239
4261
|
try {
|
4240
4262
|
let result = yield this.onFileSelected(file);
|
4241
|
-
this.
|
4263
|
+
this.formModel.patchValue({ uploadResult: result !== null && result !== void 0 ? result : null });
|
4242
4264
|
}
|
4243
4265
|
catch (e) {
|
4244
4266
|
// Bummer, we're not going to do anything about it though.
|
4245
4267
|
// We are not patching any of the result so any existing information remains
|
4246
4268
|
}
|
4247
4269
|
}
|
4248
|
-
else {
|
4249
|
-
this.patchFileResult(file, base64FileString);
|
4250
|
-
}
|
4251
4270
|
});
|
4252
4271
|
}
|
4253
4272
|
/**
|
@@ -4264,19 +4283,14 @@ class FileUploadComponent extends FormControlBase {
|
|
4264
4283
|
* @param base64FileString
|
4265
4284
|
* @param onFileSelectedResult
|
4266
4285
|
*/
|
4267
|
-
|
4286
|
+
patchProcessedFile(file, base64FileString) {
|
4268
4287
|
var _a;
|
4269
4288
|
(_a = this.formModel) === null || _a === void 0 ? void 0 : _a.patchValue({
|
4270
4289
|
file: file,
|
4271
4290
|
name: file === null || file === void 0 ? void 0 : file.name,
|
4272
|
-
base64FileString: base64FileString !== null && base64FileString !== void 0 ? base64FileString : null
|
4291
|
+
base64FileString: base64FileString !== null && base64FileString !== void 0 ? base64FileString : null,
|
4292
|
+
uploadResult: null
|
4273
4293
|
});
|
4274
|
-
if (onFileSelectedResult) {
|
4275
|
-
this.formModel.patchValue({ uploadResult: onFileSelectedResult });
|
4276
|
-
}
|
4277
|
-
else {
|
4278
|
-
this.formModel.patchValue({ uploadResult: null });
|
4279
|
-
}
|
4280
4294
|
}
|
4281
4295
|
/** Maps the files to an array of File objects and sends them along
|
4282
4296
|
* to the derived onMultipleFileSelected method in the hosting component
|
@@ -4313,11 +4327,13 @@ class FileUploadComponent extends FormControlBase {
|
|
4313
4327
|
}
|
4314
4328
|
}
|
4315
4329
|
FileUploadComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: FileUploadComponent, deps: [{ token: ValidationMessageService }, { token: FormGroupHelper }], target: i0.ɵɵFactoryTarget.Component });
|
4316
|
-
FileUploadComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.9", type: FileUploadComponent, selector: "ec-file-upload", inputs: { placeholder: "placeholder", fileType: "fileType", fileOutput: "fileOutput", customExtensions: "customExtensions", onFileSelected: "onFileSelected", onMultipleFilesSelected: "onMultipleFilesSelected", displayType: "displayType", buttonLabel: "buttonLabel", buttonType: "buttonType", multiSelect: "multiSelect" }, viewQueries: [{ propertyName: "fileInput", first: true, predicate: ["fileInput"], descendants: true, read: ElementRef, static: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<ec-form-group [label]=\"label\"\r\n [formGroup]=\"formModel\"\r\n [helpPopover]=\"helpPopover\"\r\n [helpPopoverPosition]=\"helpPopoverPosition\"\r\n class=\"mb-0\">\r\n <div class=\"d-flex control-group\">\r\n <div class=\"d-flex flex-grow position-relative\">\r\n <input #fileInput\r\n id=\"{{inputId}}_input\"\r\n type=\"file\"\r\n tabindex=\"-1\"\r\n [attr.accept]=\"fileTypeAccept\"\r\n (change)=\"fileChange($event.target.files)\"\r\n [class.has-value]=\"displayType === 'file' ? formModel?.get('name').value : undefined\"\r\n [attr.multiple]=\"multiSelect ? 'multiple' : undefined\">\r\n
|
4330
|
+
FileUploadComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "15.2.9", type: FileUploadComponent, selector: "ec-file-upload", inputs: { formModel: "formModel", placeholder: "placeholder", fileType: "fileType", fileOutput: "fileOutput", customExtensions: "customExtensions", onFileSelected: "onFileSelected", onMultipleFilesSelected: "onMultipleFilesSelected", displayType: "displayType", buttonLabel: "buttonLabel", buttonType: "buttonType", multiSelect: "multiSelect" }, viewQueries: [{ propertyName: "fileInput", first: true, predicate: ["fileInput"], descendants: true, read: ElementRef, static: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<ec-form-group [label]=\"label\"\r\n [formGroup]=\"formModel\"\r\n [helpPopover]=\"helpPopover\"\r\n [helpPopoverPosition]=\"helpPopoverPosition\"\r\n class=\"mb-0\">\r\n <div class=\"d-flex control-group\">\r\n <div class=\"d-flex flex-grow position-relative\">\r\n <input #fileInput\r\n id=\"{{inputId}}_input\"\r\n type=\"file\"\r\n tabindex=\"-1\"\r\n [attr.accept]=\"fileTypeAccept\"\r\n (change)=\"fileChange($event.target.files)\"\r\n [class.has-value]=\"displayType === 'file' ? formModel?.get('name').value : undefined\"\r\n [attr.multiple]=\"multiSelect ? 'multiple' : undefined\">\r\n <ec-form-control *ngIf=\"displayType === 'file'\"\r\n id=\"{{inputId}}_formControl\"\r\n class=\"text-truncate\"\r\n [required]=\"required\"\r\n [pending]=\"pending || formModel?.pending\">\r\n <input id=\"{{inputId}}_name\"\r\n [formControl]=\"formModel?.get('name')\"\r\n type=\"text\"\r\n [placeholder]=\"placeholder\"\r\n [tabindex]=\"-1\">\r\n </ec-form-control>\r\n </div>\r\n <ec-button *ngIf=\"displayType === 'file'\"\r\n #browseBtn\r\n id=\"{{inputId}}_browseBtn\"\r\n (clicked)=\"fileInput.click()\"\r\n type=\"secondary\"\r\n [tabindex]=\"tabindex\"\r\n [disabled]=\"formModel?.get('name').disabled\"\r\n label=\"Browse\"\r\n [autofocus]=\"autofocus\">\r\n </ec-button>\r\n </div>\r\n <ec-button *ngIf=\"displayType === 'button'\"\r\n id=\"{{inputId}}_btn\"\r\n [pending]=\"pending\"\r\n [type]=\"buttonType\"\r\n [label]=\"buttonLabel ?? 'Browse_TC' | translate\"\r\n (clicked)=\"fileInput.click()\"\r\n style=\"width: 100%;\">\r\n </ec-button>\r\n</ec-form-group>", styles: [":host{display:block;margin-bottom:1rem}ec-form-control{margin-bottom:0}ec-form-control ::ng-deep>.ec-focus-ring{display:none!important}input[type=file]{opacity:0;display:block;position:absolute;top:0;left:0;width:100%;height:100%;z-index:1;cursor:pointer}input[type=file].has-value{width:calc(100% - 1.5rem)}ec-button{--ec-button-border-color-secondary: var(--ec-form-control-border-color);--ec-button-color-icon-secondary: var(--ec-color-icon)}\n"], dependencies: [{ kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i4.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i4.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i4.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i4.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i4.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: ButtonComponent, selector: "ec-button", inputs: ["id", "disabled", "icon", "label", "badge", "tabindex", "type", "pending", "pendingIcon", "customTemplate", "isSubmit", "autofocus"], outputs: ["clicked"] }, { kind: "component", type: FormControlComponent, selector: "ec-form-control", inputs: ["id", "icon", "actionIcon", "showClear", "pending", "required", "readonly"], outputs: ["actionClicked"] }, { kind: "component", type: FormGroupComponent, selector: "ec-form-group", inputs: ["id", "label", "formGroup", "labelPosition", "overrideValidationError", "hideValidationMessage", "helpPopover", "helpPopoverPosition"] }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }] });
|
4317
4331
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "15.2.9", ngImport: i0, type: FileUploadComponent, decorators: [{
|
4318
4332
|
type: Component,
|
4319
|
-
args: [{ selector: "ec-file-upload", template: "<ec-form-group [label]=\"label\"\r\n [formGroup]=\"formModel\"\r\n [helpPopover]=\"helpPopover\"\r\n [helpPopoverPosition]=\"helpPopoverPosition\"\r\n class=\"mb-0\">\r\n <div class=\"d-flex control-group\">\r\n <div class=\"d-flex flex-grow position-relative\">\r\n <input #fileInput\r\n id=\"{{inputId}}_input\"\r\n type=\"file\"\r\n tabindex=\"-1\"\r\n [attr.accept]=\"fileTypeAccept\"\r\n (change)=\"fileChange($event.target.files)\"\r\n [class.has-value]=\"displayType === 'file' ? formModel?.get('name').value : undefined\"\r\n [attr.multiple]=\"multiSelect ? 'multiple' : undefined\">\r\n
|
4320
|
-
}], ctorParameters: function () { return [{ type: ValidationMessageService }, { type: FormGroupHelper }]; }, propDecorators: {
|
4333
|
+
args: [{ selector: "ec-file-upload", template: "<ec-form-group [label]=\"label\"\r\n [formGroup]=\"formModel\"\r\n [helpPopover]=\"helpPopover\"\r\n [helpPopoverPosition]=\"helpPopoverPosition\"\r\n class=\"mb-0\">\r\n <div class=\"d-flex control-group\">\r\n <div class=\"d-flex flex-grow position-relative\">\r\n <input #fileInput\r\n id=\"{{inputId}}_input\"\r\n type=\"file\"\r\n tabindex=\"-1\"\r\n [attr.accept]=\"fileTypeAccept\"\r\n (change)=\"fileChange($event.target.files)\"\r\n [class.has-value]=\"displayType === 'file' ? formModel?.get('name').value : undefined\"\r\n [attr.multiple]=\"multiSelect ? 'multiple' : undefined\">\r\n <ec-form-control *ngIf=\"displayType === 'file'\"\r\n id=\"{{inputId}}_formControl\"\r\n class=\"text-truncate\"\r\n [required]=\"required\"\r\n [pending]=\"pending || formModel?.pending\">\r\n <input id=\"{{inputId}}_name\"\r\n [formControl]=\"formModel?.get('name')\"\r\n type=\"text\"\r\n [placeholder]=\"placeholder\"\r\n [tabindex]=\"-1\">\r\n </ec-form-control>\r\n </div>\r\n <ec-button *ngIf=\"displayType === 'file'\"\r\n #browseBtn\r\n id=\"{{inputId}}_browseBtn\"\r\n (clicked)=\"fileInput.click()\"\r\n type=\"secondary\"\r\n [tabindex]=\"tabindex\"\r\n [disabled]=\"formModel?.get('name').disabled\"\r\n label=\"Browse\"\r\n [autofocus]=\"autofocus\">\r\n </ec-button>\r\n </div>\r\n <ec-button *ngIf=\"displayType === 'button'\"\r\n id=\"{{inputId}}_btn\"\r\n [pending]=\"pending\"\r\n [type]=\"buttonType\"\r\n [label]=\"buttonLabel ?? 'Browse_TC' | translate\"\r\n (clicked)=\"fileInput.click()\"\r\n style=\"width: 100%;\">\r\n </ec-button>\r\n</ec-form-group>", styles: [":host{display:block;margin-bottom:1rem}ec-form-control{margin-bottom:0}ec-form-control ::ng-deep>.ec-focus-ring{display:none!important}input[type=file]{opacity:0;display:block;position:absolute;top:0;left:0;width:100%;height:100%;z-index:1;cursor:pointer}input[type=file].has-value{width:calc(100% - 1.5rem)}ec-button{--ec-button-border-color-secondary: var(--ec-form-control-border-color);--ec-button-color-icon-secondary: var(--ec-color-icon)}\n"] }]
|
4334
|
+
}], ctorParameters: function () { return [{ type: ValidationMessageService }, { type: FormGroupHelper }]; }, propDecorators: { formModel: [{
|
4335
|
+
type: Input
|
4336
|
+
}], placeholder: [{
|
4321
4337
|
type: Input
|
4322
4338
|
}], fileType: [{
|
4323
4339
|
type: Input
|
@@ -10696,6 +10712,10 @@ class PageBaseComponent {
|
|
10696
10712
|
onSave(event) {
|
10697
10713
|
return __awaiter(this, void 0, void 0, function* () {
|
10698
10714
|
this.formGroup.markAllAsTouched();
|
10715
|
+
// If the form has pending async validators, wait for it them to complete before proceeding
|
10716
|
+
if (this.formGroup.pending) {
|
10717
|
+
yield this.formGroup.statusChanges.pipe(filter(status => status !== 'PENDING'), take(1), takeUntil(this.destroyed)).toPromise();
|
10718
|
+
}
|
10699
10719
|
if (this.formGroup.valid) {
|
10700
10720
|
yield this.save();
|
10701
10721
|
}
|