UNPKG

@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
/* 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