@ngspot/ngx-errors
Version:
<p align="center"> <img width="20%" height="20%" src="https://github.com/DmitryEfimenko/ngspot/blob/main/packages/ngx-errors/package/assets/logo.png?raw=true"> </p>
105 lines • 11.8 kB
JavaScript
/* eslint-disable @angular-eslint/directive-selector */
import { Directive, signal, input, computed, } from '@angular/core';
import { FormArray, FormControl, FormGroup, } from '@angular/forms';
import { NgxErrorsBase } from './errors-base.directive';
import { ControlInstanceError, ControlNotFoundError, NoControlError, ParentFormGroupNotFoundError, } from './ngx-errors';
import * as i0 from "@angular/core";
/**
* Directive to hook into the errors of a given control.
*
* Example:
*
* ```ts
* \@Component({
* template: `
* <div [ngxErrors]="myControl">
* <div ngxError="required">This input is required</div>
* </div>
* `
* })
* export class MyComponent {
* myControl = new FormControl('', Validators.required)
* }
* ```
* In case the `ngxErrors` directive is a child of a [formGroup], you can specify
* the control by the control name similarly how you'd do it with formControlName:
*
* ```ts
* \@Component({
* template: `
* <form [formGroup]="form">
* <div ngxErrors="firstName">
* <div ngxError="required">This input is required</div>
* </div>
* </form>
* `
* })
* export class MyComponent {
* form = this.fb.group({
* firstName: ['', Validators.required]
* });
* constructor(private fb: FormBuilder) {}
* }
* ```
*/
export class ErrorsDirective extends NgxErrorsBase {
constructor() {
super(...arguments);
this.controlInput = input.required({
alias: 'ngxErrors',
});
this.resolvedControl = computed(() => {
const controlInput = this.controlInput();
// initialize directive only after control input was set AND after
// afterViewInit since parentFormGroupDirective might not be resolved
// before that
if (!this.afterViewInitComplete()) {
return;
}
if (!controlInput) {
throw new NoControlError();
}
if (typeof controlInput === 'string') {
if (!this.parentControlContainer) {
throw new ParentFormGroupNotFoundError(controlInput);
}
const control = this.parentControlContainer.control?.get(controlInput);
if (control == null) {
throw new ControlNotFoundError(controlInput);
}
return control;
}
if (!this.isAbstractControl(controlInput)) {
throw new ControlInstanceError();
}
return controlInput;
});
this.afterViewInitComplete = signal(false);
}
ngAfterViewInit() {
setTimeout(() => {
// Use of the setTimeout to ensure that the controlInput was surely set
// in all cases. In particular the edge-case where ngModelGroup
// declared via template driven forms results in the control being
// set later than ngAfterViewInit life-cycle hook is called
this.afterViewInitComplete.set(true);
}, 0);
}
isAbstractControl(control) {
return (control instanceof FormControl ||
control instanceof FormArray ||
control instanceof FormGroup);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.7", ngImport: i0, type: ErrorsDirective, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "17.3.7", type: ErrorsDirective, isStandalone: true, selector: "[ngxErrors]", inputs: { controlInput: { classPropertyName: "controlInput", publicName: "ngxErrors", isSignal: true, isRequired: true, transformFunction: null } }, providers: [{ provide: NgxErrorsBase, useExisting: ErrorsDirective }], exportAs: ["ngxErrors"], usesInheritance: true, ngImport: i0 }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.7", ngImport: i0, type: ErrorsDirective, decorators: [{
type: Directive,
args: [{
selector: '[ngxErrors]',
exportAs: 'ngxErrors',
standalone: true,
providers: [{ provide: NgxErrorsBase, useExisting: ErrorsDirective }],
}]
}] });
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXJyb3JzLmRpcmVjdGl2ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL25neC1lcnJvcnMvcGFja2FnZS9zcmMvbGliL2Vycm9ycy5kaXJlY3RpdmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsdURBQXVEO0FBQ3ZELE9BQU8sRUFFTCxTQUFTLEVBQ1QsTUFBTSxFQUNOLEtBQUssRUFDTCxRQUFRLEdBQ1QsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUVMLFNBQVMsRUFDVCxXQUFXLEVBQ1gsU0FBUyxHQUNWLE1BQU0sZ0JBQWdCLENBQUM7QUFFeEIsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ3hELE9BQU8sRUFDTCxvQkFBb0IsRUFDcEIsb0JBQW9CLEVBQ3BCLGNBQWMsRUFDZCw0QkFBNEIsR0FDN0IsTUFBTSxjQUFjLENBQUM7O0FBRXRCOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBcUNHO0FBT0gsTUFBTSxPQUFPLGVBQWdCLFNBQVEsYUFBYTtJQU5sRDs7UUFPRSxpQkFBWSxHQUFHLEtBQUssQ0FBQyxRQUFRLENBQTJCO1lBQ3RELEtBQUssRUFBRSxXQUFXO1NBQ25CLENBQUMsQ0FBQztRQUVILG9CQUFlLEdBQUcsUUFBUSxDQUFDLEdBQUcsRUFBRTtZQUM5QixNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUM7WUFFekMsa0VBQWtFO1lBQ2xFLHFFQUFxRTtZQUNyRSxjQUFjO1lBQ2QsSUFBSSxDQUFDLElBQUksQ0FBQyxxQkFBcUIsRUFBRSxFQUFFLENBQUM7Z0JBQ2xDLE9BQU87WUFDVCxDQUFDO1lBRUQsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO2dCQUNsQixNQUFNLElBQUksY0FBYyxFQUFFLENBQUM7WUFDN0IsQ0FBQztZQUVELElBQUksT0FBTyxZQUFZLEtBQUssUUFBUSxFQUFFLENBQUM7Z0JBQ3JDLElBQUksQ0FBQyxJQUFJLENBQUMsc0JBQXNCLEVBQUUsQ0FBQztvQkFDakMsTUFBTSxJQUFJLDRCQUE0QixDQUFDLFlBQVksQ0FBQyxDQUFDO2dCQUN2RCxDQUFDO2dCQUVELE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxPQUFPLEVBQUUsR0FBRyxDQUFDLFlBQVksQ0FBQyxDQUFDO2dCQUV2RSxJQUFJLE9BQU8sSUFBSSxJQUFJLEVBQUUsQ0FBQztvQkFDcEIsTUFBTSxJQUFJLG9CQUFvQixDQUFDLFlBQVksQ0FBQyxDQUFDO2dCQUMvQyxDQUFDO2dCQUVELE9BQU8sT0FBTyxDQUFDO1lBQ2pCLENBQUM7WUFFRCxJQUFJLENBQUMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLFlBQVksQ0FBQyxFQUFFLENBQUM7Z0JBQzFDLE1BQU0sSUFBSSxvQkFBb0IsRUFBRSxDQUFDO1lBQ25DLENBQUM7WUFFRCxPQUFPLFlBQVksQ0FBQztRQUN0QixDQUFDLENBQUMsQ0FBQztRQUVLLDBCQUFxQixHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztLQXFCL0M7SUFuQkMsZUFBZTtRQUNiLFVBQVUsQ0FBQyxHQUFHLEVBQUU7WUFDZCx1RUFBdUU7WUFDdkUsK0RBQStEO1lBQy9ELGtFQUFrRTtZQUNsRSwyREFBMkQ7WUFDM0QsSUFBSSxDQUFDLHFCQUFxQixDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN2QyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDUixDQUFDO0lBRU8saUJBQWlCLENBQ3ZCLE9BQWlDO1FBRWpDLE9BQU8sQ0FDTCxPQUFPLFlBQVksV0FBVztZQUM5QixPQUFPLFlBQVksU0FBUztZQUM1QixPQUFPLFlBQVksU0FBUyxDQUM3QixDQUFDO0lBQ0osQ0FBQzs4R0E1RFUsZUFBZTtrR0FBZixlQUFlLCtNQUZmLENBQUMsRUFBRSxPQUFPLEVBQUUsYUFBYSxFQUFFLFdBQVcsRUFBRSxlQUFlLEVBQUUsQ0FBQzs7MkZBRTFELGVBQWU7a0JBTjNCLFNBQVM7bUJBQUM7b0JBQ1QsUUFBUSxFQUFFLGFBQWE7b0JBQ3ZCLFFBQVEsRUFBRSxXQUFXO29CQUNyQixVQUFVLEVBQUUsSUFBSTtvQkFDaEIsU0FBUyxFQUFFLENBQUMsRUFBRSxPQUFPLEVBQUUsYUFBYSxFQUFFLFdBQVcsaUJBQWlCLEVBQUUsQ0FBQztpQkFDdEUiLCJzb3VyY2VzQ29udGVudCI6WyIvKiBlc2xpbnQtZGlzYWJsZSBAYW5ndWxhci1lc2xpbnQvZGlyZWN0aXZlLXNlbGVjdG9yICovXHJcbmltcG9ydCB7XHJcbiAgQWZ0ZXJWaWV3SW5pdCxcclxuICBEaXJlY3RpdmUsXHJcbiAgc2lnbmFsLFxyXG4gIGlucHV0LFxyXG4gIGNvbXB1dGVkLFxyXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQge1xyXG4gIEFic3RyYWN0Q29udHJvbCxcclxuICBGb3JtQXJyYXksXHJcbiAgRm9ybUNvbnRyb2wsXHJcbiAgRm9ybUdyb3VwLFxyXG59IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcclxuXHJcbmltcG9ydCB7IE5neEVycm9yc0Jhc2UgfSBmcm9tICcuL2Vycm9ycy1iYXNlLmRpcmVjdGl2ZSc7XHJcbmltcG9ydCB7XHJcbiAgQ29udHJvbEluc3RhbmNlRXJyb3IsXHJcbiAgQ29udHJvbE5vdEZvdW5kRXJyb3IsXHJcbiAgTm9Db250cm9sRXJyb3IsXHJcbiAgUGFyZW50Rm9ybUdyb3VwTm90Rm91bmRFcnJvcixcclxufSBmcm9tICcuL25neC1lcnJvcnMnO1xyXG5cclxuLyoqXHJcbiAqIERpcmVjdGl2ZSB0byBob29rIGludG8gdGhlIGVycm9ycyBvZiBhIGdpdmVuIGNvbnRyb2wuXHJcbiAqXHJcbiAqIEV4YW1wbGU6XHJcbiAqXHJcbiAqIGBgYHRzXHJcbiAqIFxcQENvbXBvbmVudCh7XHJcbiAqICAgdGVtcGxhdGU6IGBcclxuICogICA8ZGl2IFtuZ3hFcnJvcnNdPVwibXlDb250cm9sXCI+XHJcbiAqICAgICA8ZGl2IG5neEVycm9yPVwicmVxdWlyZWRcIj5UaGlzIGlucHV0IGlzIHJlcXVpcmVkPC9kaXY+XHJcbiAqICAgPC9kaXY+XHJcbiAqICAgYFxyXG4gKiB9KVxyXG4gKiBleHBvcnQgY2xhc3MgTXlDb21wb25lbnQge1xyXG4gKiAgIG15Q29udHJvbCA9IG5ldyBGb3JtQ29udHJvbCgnJywgVmFsaWRhdG9ycy5yZXF1aXJlZClcclxuICogfVxyXG4gKiBgYGBcclxuICogSW4gY2FzZSB0aGUgYG5neEVycm9yc2AgZGlyZWN0aXZlIGlzIGEgY2hpbGQgb2YgYSBbZm9ybUdyb3VwXSwgeW91IGNhbiBzcGVjaWZ5XHJcbiAqIHRoZSBjb250cm9sIGJ5IHRoZSBjb250cm9sIG5hbWUgc2ltaWxhcmx5IGhvdyB5b3UnZCBkbyBpdCB3aXRoIGZvcm1Db250cm9sTmFtZTpcclxuICpcclxuICogYGBgdHNcclxuICogXFxAQ29tcG9uZW50KHtcclxuICogICB0ZW1wbGF0ZTogYFxyXG4gKiAgIDxmb3JtIFtmb3JtR3JvdXBdPVwiZm9ybVwiPlxyXG4gKiAgICAgPGRpdiBuZ3hFcnJvcnM9XCJmaXJzdE5hbWVcIj5cclxuICogICAgICAgPGRpdiBuZ3hFcnJvcj1cInJlcXVpcmVkXCI+VGhpcyBpbnB1dCBpcyByZXF1aXJlZDwvZGl2PlxyXG4gKiAgICAgPC9kaXY+XHJcbiAqICAgPC9mb3JtPlxyXG4gKiAgIGBcclxuICogfSlcclxuICogZXhwb3J0IGNsYXNzIE15Q29tcG9uZW50IHtcclxuICogICBmb3JtID0gdGhpcy5mYi5ncm91cCh7XHJcbiAqICAgICBmaXJzdE5hbWU6IFsnJywgVmFsaWRhdG9ycy5yZXF1aXJlZF1cclxuICogICB9KTtcclxuICogICBjb25zdHJ1Y3Rvcihwcml2YXRlIGZiOiBGb3JtQnVpbGRlcikge31cclxuICogfVxyXG4gKiBgYGBcclxuICovXHJcbkBEaXJlY3RpdmUoe1xyXG4gIHNlbGVjdG9yOiAnW25neEVycm9yc10nLFxyXG4gIGV4cG9ydEFzOiAnbmd4RXJyb3JzJyxcclxuICBzdGFuZGFsb25lOiB0cnVlLFxyXG4gIHByb3ZpZGVyczogW3sgcHJvdmlkZTogTmd4RXJyb3JzQmFzZSwgdXNlRXhpc3Rpbmc6IEVycm9yc0RpcmVjdGl2ZSB9XSxcclxufSlcclxuZXhwb3J0IGNsYXNzIEVycm9yc0RpcmVjdGl2ZSBleHRlbmRzIE5neEVycm9yc0Jhc2UgaW1wbGVtZW50cyBBZnRlclZpZXdJbml0IHtcclxuICBjb250cm9sSW5wdXQgPSBpbnB1dC5yZXF1aXJlZDxBYnN0cmFjdENvbnRyb2wgfCBzdHJpbmc+KHtcclxuICAgIGFsaWFzOiAnbmd4RXJyb3JzJyxcclxuICB9KTtcclxuXHJcbiAgcmVzb2x2ZWRDb250cm9sID0gY29tcHV0ZWQoKCkgPT4ge1xyXG4gICAgY29uc3QgY29udHJvbElucHV0ID0gdGhpcy5jb250cm9sSW5wdXQoKTtcclxuXHJcbiAgICAvLyBpbml0aWFsaXplIGRpcmVjdGl2ZSBvbmx5IGFmdGVyIGNvbnRyb2wgaW5wdXQgd2FzIHNldCBBTkQgYWZ0ZXJcclxuICAgIC8vIGFmdGVyVmlld0luaXQgc2luY2UgcGFyZW50Rm9ybUdyb3VwRGlyZWN0aXZlIG1pZ2h0IG5vdCBiZSByZXNvbHZlZFxyXG4gICAgLy8gYmVmb3JlIHRoYXRcclxuICAgIGlmICghdGhpcy5hZnRlclZpZXdJbml0Q29tcGxldGUoKSkge1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKCFjb250cm9sSW5wdXQpIHtcclxuICAgICAgdGhyb3cgbmV3IE5vQ29udHJvbEVycm9yKCk7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHR5cGVvZiBjb250cm9sSW5wdXQgPT09ICdzdHJpbmcnKSB7XHJcbiAgICAgIGlmICghdGhpcy5wYXJlbnRDb250cm9sQ29udGFpbmVyKSB7XHJcbiAgICAgICAgdGhyb3cgbmV3IFBhcmVudEZvcm1Hcm91cE5vdEZvdW5kRXJyb3IoY29udHJvbElucHV0KTtcclxuICAgICAgfVxyXG5cclxuICAgICAgY29uc3QgY29udHJvbCA9IHRoaXMucGFyZW50Q29udHJvbENvbnRhaW5lci5jb250cm9sPy5nZXQoY29udHJvbElucHV0KTtcclxuXHJcbiAgICAgIGlmIChjb250cm9sID09IG51bGwpIHtcclxuICAgICAgICB0aHJvdyBuZXcgQ29udHJvbE5vdEZvdW5kRXJyb3IoY29udHJvbElucHV0KTtcclxuICAgICAgfVxyXG5cclxuICAgICAgcmV0dXJuIGNvbnRyb2w7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKCF0aGlzLmlzQWJzdHJhY3RDb250cm9sKGNvbnRyb2xJbnB1dCkpIHtcclxuICAgICAgdGhyb3cgbmV3IENvbnRyb2xJbnN0YW5jZUVycm9yKCk7XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIGNvbnRyb2xJbnB1dDtcclxuICB9KTtcclxuXHJcbiAgcHJpdmF0ZSBhZnRlclZpZXdJbml0Q29tcGxldGUgPSBzaWduYWwoZmFsc2UpO1xyXG5cclxuICBuZ0FmdGVyVmlld0luaXQoKSB7XHJcbiAgICBzZXRUaW1lb3V0KCgpID0+IHtcclxuICAgICAgLy8gVXNlIG9mIHRoZSBzZXRUaW1lb3V0IHRvIGVuc3VyZSB0aGF0IHRoZSBjb250cm9sSW5wdXQgd2FzIHN1cmVseSBzZXRcclxuICAgICAgLy8gaW4gYWxsIGNhc2VzLiBJbiBwYXJ0aWN1bGFyIHRoZSBlZGdlLWNhc2Ugd2hlcmUgbmdNb2RlbEdyb3VwXHJcbiAgICAgIC8vIGRlY2xhcmVkIHZpYSB0ZW1wbGF0ZSBkcml2ZW4gZm9ybXMgcmVzdWx0cyBpbiB0aGUgY29udHJvbCBiZWluZ1xyXG4gICAgICAvLyBzZXQgbGF0ZXIgdGhhbiBuZ0FmdGVyVmlld0luaXQgbGlmZS1jeWNsZSBob29rIGlzIGNhbGxlZFxyXG4gICAgICB0aGlzLmFmdGVyVmlld0luaXRDb21wbGV0ZS5zZXQodHJ1ZSk7XHJcbiAgICB9LCAwKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgaXNBYnN0cmFjdENvbnRyb2woXHJcbiAgICBjb250cm9sOiBBYnN0cmFjdENvbnRyb2wgfCBzdHJpbmcsXHJcbiAgKTogY29udHJvbCBpcyBBYnN0cmFjdENvbnRyb2wge1xyXG4gICAgcmV0dXJuIChcclxuICAgICAgY29udHJvbCBpbnN0YW5jZW9mIEZvcm1Db250cm9sIHx8XHJcbiAgICAgIGNvbnRyb2wgaW5zdGFuY2VvZiBGb3JtQXJyYXkgfHxcclxuICAgICAgY29udHJvbCBpbnN0YW5jZW9mIEZvcm1Hcm91cFxyXG4gICAgKTtcclxuICB9XHJcbn1cclxuIl19