ngx-mat-form-errors 0.0.3 → 0.0.5
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/README.md +175 -13
- package/esm2022/lib/error/error.component.mjs +51 -0
- package/esm2022/lib/ngx-form-errors.module.mjs +6 -5
- package/esm2022/lib/services/error.service.mjs +31 -0
- package/esm2022/public-api.mjs +4 -3
- package/fesm2022/ngx-mat-form-errors.mjs +83 -18
- package/fesm2022/ngx-mat-form-errors.mjs.map +1 -1
- package/lib/error/error.component.d.ts +19 -0
- package/lib/ngx-form-errors.module.d.ts +2 -1
- package/lib/services/error.service.d.ts +6 -0
- package/package.json +1 -1
- package/public-api.d.ts +3 -2
package/README.md
CHANGED
|
@@ -1,24 +1,186 @@
|
|
|
1
|
-
#
|
|
1
|
+
# ngx-mat-form-errors
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A lightweight Angular library that automatically displays validation errors for Angular Material forms. Stop writing repetitive error message logic!
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
[](https://www.npmjs.com/package/ngx-mat-form-errors)
|
|
6
|
+
[](https://www.npmjs.com/package/ngx-mat-form-errors)
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
> Note: Don't forget to add `--project ngx-form-errors` or else it will be added to the default project in your `angular.json` file.
|
|
8
|
+
## Installation
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
```bash
|
|
11
|
+
npm install ngx-mat-form-errors
|
|
12
|
+
```
|
|
11
13
|
|
|
12
|
-
|
|
14
|
+
## Quick Usage
|
|
13
15
|
|
|
14
|
-
|
|
16
|
+
### 1. Import the module
|
|
15
17
|
|
|
16
|
-
|
|
18
|
+
**For standalone components:**
|
|
19
|
+
```typescript
|
|
20
|
+
import { NgxFormErrorsModule } from 'ngx-mat-form-errors';
|
|
17
21
|
|
|
18
|
-
|
|
22
|
+
@Component({
|
|
23
|
+
// ...
|
|
24
|
+
imports: [
|
|
25
|
+
// ... other imports
|
|
26
|
+
NgxFormErrorsModule,
|
|
27
|
+
ReactiveFormsModule,
|
|
28
|
+
MatFormFieldModule,
|
|
29
|
+
MatInputModule
|
|
30
|
+
]
|
|
31
|
+
})
|
|
32
|
+
export class YourComponent {}
|
|
33
|
+
```
|
|
19
34
|
|
|
20
|
-
|
|
35
|
+
**For NgModules:**
|
|
36
|
+
```typescript
|
|
37
|
+
import { NgxFormErrorsModule } from 'ngx-mat-form-errors';
|
|
38
|
+
|
|
39
|
+
@NgModule({
|
|
40
|
+
imports: [
|
|
41
|
+
// ... other imports
|
|
42
|
+
NgxFormErrorsModule,
|
|
43
|
+
ReactiveFormsModule,
|
|
44
|
+
MatFormFieldModule,
|
|
45
|
+
MatInputModule
|
|
46
|
+
]
|
|
47
|
+
})
|
|
48
|
+
export class AppModule {}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### 2. Create a form
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
|
55
|
+
|
|
56
|
+
export class YourComponent {
|
|
57
|
+
form: FormGroup;
|
|
58
|
+
|
|
59
|
+
constructor(private fb: FormBuilder) {
|
|
60
|
+
this.form = this.fb.group({
|
|
61
|
+
email: ['', [Validators.required, Validators.email]],
|
|
62
|
+
password: ['', [Validators.required, Validators.minLength(8)]]
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### 3. Add to template
|
|
69
|
+
|
|
70
|
+
```html
|
|
71
|
+
<form [formGroup]="form">
|
|
72
|
+
<!-- Email field -->
|
|
73
|
+
<mat-form-field>
|
|
74
|
+
<mat-label>Email</mat-label>
|
|
75
|
+
<input matInput formControlName="email">
|
|
76
|
+
</mat-form-field>
|
|
77
|
+
<ngx-error field="email" label="Email"></ngx-error>
|
|
78
|
+
|
|
79
|
+
<!-- Password field -->
|
|
80
|
+
<mat-form-field>
|
|
81
|
+
<mat-label>Password</mat-label>
|
|
82
|
+
<input matInput type="password" formControlName="password">
|
|
83
|
+
</mat-form-field>
|
|
84
|
+
<ngx-error field="password" label="Password"></ngx-error>
|
|
85
|
+
</form>
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
That's it! Errors will automatically show when fields are invalid and touched.
|
|
89
|
+
|
|
90
|
+
## Examples
|
|
91
|
+
|
|
92
|
+
### Basic Form
|
|
93
|
+
|
|
94
|
+
```html
|
|
95
|
+
<mat-form-field>
|
|
96
|
+
<mat-label>Username</mat-label>
|
|
97
|
+
<input matInput formControlName="username">
|
|
98
|
+
</mat-form-field>
|
|
99
|
+
<ngx-error field="username" label="Username"></ngx-error>
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Custom Label
|
|
103
|
+
|
|
104
|
+
```html
|
|
105
|
+
<ngx-error field="email" label="Email address"></ngx-error>
|
|
106
|
+
<!-- Displays: "Email address is required" instead of "Email is required" -->
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Nested Form Groups
|
|
110
|
+
|
|
111
|
+
```html
|
|
112
|
+
<div formGroupName="address">
|
|
113
|
+
<mat-form-field>
|
|
114
|
+
<mat-label>Street</mat-label>
|
|
115
|
+
<input matInput formControlName="street">
|
|
116
|
+
</mat-form-field>
|
|
117
|
+
<ngx-error field="address.street" label="Street"></ngx-error>
|
|
118
|
+
</div>
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Default Error Messages
|
|
122
|
+
|
|
123
|
+
| Error | Message |
|
|
124
|
+
|-------|---------|
|
|
125
|
+
| required | `{label} is required` |
|
|
126
|
+
| email | `Invalid email format` |
|
|
127
|
+
| minlength | `{label} must be at least {requiredLength} characters` |
|
|
128
|
+
| maxlength | `{label} cannot exceed {requiredLength} characters` |
|
|
129
|
+
| pattern | `Invalid {label} format` |
|
|
130
|
+
| default | `Invalid {label}` |
|
|
131
|
+
|
|
132
|
+
## Custom Error Messages
|
|
133
|
+
|
|
134
|
+
Create a custom service:
|
|
135
|
+
|
|
136
|
+
```typescript
|
|
137
|
+
import { Injectable } from '@angular/core';
|
|
138
|
+
import { ErrorService } from 'ngx-mat-form-errors';
|
|
139
|
+
|
|
140
|
+
@Injectable({ providedIn: 'root' })
|
|
141
|
+
export class CustomErrorService extends ErrorService {
|
|
142
|
+
override getErrorMessage(errors: any, label: string): string {
|
|
143
|
+
if (errors['required']) return `Please enter your ${label}`;
|
|
144
|
+
if (errors['email']) return 'Enter a valid email address';
|
|
145
|
+
if (errors['minlength']) return `Minimum ${errors['minlength'].requiredLength} characters required`;
|
|
146
|
+
return super.getErrorMessage(errors, label);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
Add to providers:
|
|
152
|
+
|
|
153
|
+
```typescript
|
|
154
|
+
providers: [
|
|
155
|
+
{ provide: ErrorService, useClass: CustomErrorService }
|
|
156
|
+
]
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## API
|
|
160
|
+
|
|
161
|
+
### `<ngx-error>` Component
|
|
162
|
+
|
|
163
|
+
| Property | Type | Required | Description |
|
|
164
|
+
|----------|------|----------|-------------|
|
|
165
|
+
| `field` | string | Yes | Form control name (supports nested like "address.street") |
|
|
166
|
+
| `label` | string | No | Display name (defaults to field name) |
|
|
167
|
+
|
|
168
|
+
## Styling
|
|
169
|
+
|
|
170
|
+
The component uses the `.ngx-error` class:
|
|
171
|
+
|
|
172
|
+
```css
|
|
173
|
+
.ngx-error {
|
|
174
|
+
color: #f44336;
|
|
175
|
+
font-size: 12px;
|
|
176
|
+
margin-top: 4px;
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## Requirements
|
|
181
|
+
|
|
182
|
+
- Angular 14+
|
|
183
|
+
- @angular/forms
|
|
184
|
+
- @angular/material (optional)
|
|
21
185
|
|
|
22
|
-
## Further help
|
|
23
186
|
|
|
24
|
-
To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.dev/tools/cli) page.
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { Component, Input } from '@angular/core';
|
|
2
|
+
import { ReactiveFormsModule } from '@angular/forms';
|
|
3
|
+
import { CommonModule } from '@angular/common';
|
|
4
|
+
import { Subject, takeUntil } from 'rxjs';
|
|
5
|
+
import * as i0 from "@angular/core";
|
|
6
|
+
import * as i1 from "@angular/forms";
|
|
7
|
+
import * as i2 from "../services/error.service";
|
|
8
|
+
import * as i3 from "@angular/common";
|
|
9
|
+
export class ErrorComponent {
|
|
10
|
+
controlContainer;
|
|
11
|
+
errorService;
|
|
12
|
+
destroy$ = new Subject();
|
|
13
|
+
field;
|
|
14
|
+
label;
|
|
15
|
+
form;
|
|
16
|
+
errorMessage = '';
|
|
17
|
+
constructor(controlContainer, errorService) {
|
|
18
|
+
this.controlContainer = controlContainer;
|
|
19
|
+
this.errorService = errorService;
|
|
20
|
+
}
|
|
21
|
+
ngOnInit() {
|
|
22
|
+
this.form = this.controlContainer.control;
|
|
23
|
+
const control = this.form.get(this.field);
|
|
24
|
+
if (!control)
|
|
25
|
+
return;
|
|
26
|
+
control.statusChanges.pipe(takeUntil(this.destroy$))
|
|
27
|
+
.subscribe(() => {
|
|
28
|
+
if (control.errors && (control.touched || control.dirty)) {
|
|
29
|
+
this.errorMessage = this.errorService.getErrorMessage(control.errors, this.label || this.field);
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
this.errorMessage = '';
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
ngOnDestroy() {
|
|
37
|
+
this.destroy$.next();
|
|
38
|
+
this.destroy$.complete();
|
|
39
|
+
}
|
|
40
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ErrorComponent, deps: [{ token: i1.ControlContainer }, { token: i2.ErrorService }], target: i0.ɵɵFactoryTarget.Component });
|
|
41
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: ErrorComponent, isStandalone: true, selector: "ngx-error", inputs: { field: "field", label: "label" }, ngImport: i0, template: "<div class=\"ngx-error\" *ngIf=\"errorMessage\">\r\n {{ errorMessage }}\r\n</div>", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }] });
|
|
42
|
+
}
|
|
43
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ErrorComponent, decorators: [{
|
|
44
|
+
type: Component,
|
|
45
|
+
args: [{ selector: 'ngx-error', standalone: true, imports: [CommonModule, ReactiveFormsModule], template: "<div class=\"ngx-error\" *ngIf=\"errorMessage\">\r\n {{ errorMessage }}\r\n</div>" }]
|
|
46
|
+
}], ctorParameters: () => [{ type: i1.ControlContainer }, { type: i2.ErrorService }], propDecorators: { field: [{
|
|
47
|
+
type: Input
|
|
48
|
+
}], label: [{
|
|
49
|
+
type: Input
|
|
50
|
+
}] } });
|
|
51
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXJyb3IuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LWZvcm0tZXJyb3JzL3NyYy9saWIvZXJyb3IvZXJyb3IuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LWZvcm0tZXJyb3JzL3NyYy9saWIvZXJyb3IvZXJyb3IuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQVUsTUFBTSxlQUFlLENBQUM7QUFDekQsT0FBTyxFQUErQixtQkFBbUIsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ2xGLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUUvQyxPQUFPLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLE1BQU0sQ0FBQzs7Ozs7QUFTMUMsTUFBTSxPQUFPLGNBQWM7SUFVZjtJQUNBO0lBVFgsUUFBUSxHQUFHLElBQUksT0FBTyxFQUFRLENBQUM7SUFDckIsS0FBSyxDQUFVO0lBQ2YsS0FBSyxDQUFVO0lBRXhCLElBQUksQ0FBYTtJQUNqQixZQUFZLEdBQUcsRUFBRSxDQUFDO0lBRWxCLFlBQ1UsZ0JBQWtDLEVBQ2xDLFlBQTBCO1FBRDFCLHFCQUFnQixHQUFoQixnQkFBZ0IsQ0FBa0I7UUFDbEMsaUJBQVksR0FBWixZQUFZLENBQWM7SUFDakMsQ0FBQztJQUVKLFFBQVE7UUFDTixJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFvQixDQUFDO1FBRXZELE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUMxQyxJQUFJLENBQUMsT0FBTztZQUFFLE9BQU87UUFFckIsT0FBTyxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQzthQUN2RCxTQUFTLENBQUMsR0FBRyxFQUFFO1lBQ1YsSUFBSSxPQUFPLENBQUMsTUFBTSxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sSUFBSSxPQUFPLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQztnQkFDekQsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLGVBQWUsQ0FDbkQsT0FBTyxDQUFDLE1BQU0sRUFDZCxJQUFJLENBQUMsS0FBSyxJQUFJLElBQUksQ0FBQyxLQUFLLENBQ3pCLENBQUM7WUFDSixDQUFDO2lCQUFNLENBQUM7Z0JBQ04sSUFBSSxDQUFDLFlBQVksR0FBRyxFQUFFLENBQUM7WUFDekIsQ0FBQztRQUNILENBQUMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUVELFdBQVc7UUFDWCxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ3JCLElBQUksQ0FBQyxRQUFRLENBQUMsUUFBUSxFQUFFLENBQUM7SUFDM0IsQ0FBQzt3R0FwQ1ksY0FBYzs0RkFBZCxjQUFjLGlIQ2IzQixvRkFFTSwyQ0RRTSxZQUFZLGtJQUFFLG1CQUFtQjs7NEZBR2hDLGNBQWM7a0JBTjFCLFNBQVM7K0JBQ0UsV0FBVyxjQUNULElBQUksV0FDUCxDQUFDLFlBQVksRUFBRSxtQkFBbUIsQ0FBQztnSEFNbkMsS0FBSztzQkFBYixLQUFLO2dCQUNHLEtBQUs7c0JBQWIsS0FBSyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgSW5wdXQsIE9uSW5pdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBDb250cm9sQ29udGFpbmVyLCBGb3JtR3JvdXAsIFJlYWN0aXZlRm9ybXNNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XHJcbmltcG9ydCB7IENvbW1vbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XHJcbmltcG9ydCB7IEVycm9yU2VydmljZSB9IGZyb20gJy4uL3NlcnZpY2VzL2Vycm9yLnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBTdWJqZWN0LCB0YWtlVW50aWwgfSBmcm9tICdyeGpzJztcclxuXHJcblxyXG5AQ29tcG9uZW50KHtcclxuICBzZWxlY3RvcjogJ25neC1lcnJvcicsXHJcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcclxuICBpbXBvcnRzOiBbQ29tbW9uTW9kdWxlLCBSZWFjdGl2ZUZvcm1zTW9kdWxlXSxcclxuICB0ZW1wbGF0ZVVybDogJy4vZXJyb3IuY29tcG9uZW50Lmh0bWwnXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBFcnJvckNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCB7XHJcblxyXG4gZGVzdHJveSQgPSBuZXcgU3ViamVjdDx2b2lkPigpO1xyXG4gIEBJbnB1dCgpIGZpZWxkITogc3RyaW5nO1xyXG4gIEBJbnB1dCgpIGxhYmVsPzogc3RyaW5nO1xyXG5cclxuICBmb3JtITogRm9ybUdyb3VwO1xyXG4gIGVycm9yTWVzc2FnZSA9ICcnO1xyXG5cclxuICBjb25zdHJ1Y3RvcihcclxuICAgIHByaXZhdGUgY29udHJvbENvbnRhaW5lcjogQ29udHJvbENvbnRhaW5lcixcclxuICAgIHByaXZhdGUgZXJyb3JTZXJ2aWNlOiBFcnJvclNlcnZpY2VcclxuICApIHt9XHJcblxyXG4gIG5nT25Jbml0KCkge1xyXG4gICAgdGhpcy5mb3JtID0gdGhpcy5jb250cm9sQ29udGFpbmVyLmNvbnRyb2wgYXMgRm9ybUdyb3VwO1xyXG5cclxuICAgIGNvbnN0IGNvbnRyb2wgPSB0aGlzLmZvcm0uZ2V0KHRoaXMuZmllbGQpO1xyXG4gICAgaWYgKCFjb250cm9sKSByZXR1cm47XHJcblxyXG4gICAgY29udHJvbC5zdGF0dXNDaGFuZ2VzLnBpcGUodGFrZVVudGlsKHRoaXMuZGVzdHJveSQpKVxyXG4uc3Vic2NyaWJlKCgpID0+IHtcclxuICAgICAgaWYgKGNvbnRyb2wuZXJyb3JzICYmIChjb250cm9sLnRvdWNoZWQgfHwgY29udHJvbC5kaXJ0eSkpIHtcclxuICAgICAgICB0aGlzLmVycm9yTWVzc2FnZSA9IHRoaXMuZXJyb3JTZXJ2aWNlLmdldEVycm9yTWVzc2FnZShcclxuICAgICAgICAgIGNvbnRyb2wuZXJyb3JzLFxyXG4gICAgICAgICAgdGhpcy5sYWJlbCB8fCB0aGlzLmZpZWxkXHJcbiAgICAgICAgKTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICB0aGlzLmVycm9yTWVzc2FnZSA9ICcnO1xyXG4gICAgICB9XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIG5nT25EZXN0cm95KCkge1xyXG4gIHRoaXMuZGVzdHJveSQubmV4dCgpO1xyXG4gIHRoaXMuZGVzdHJveSQuY29tcGxldGUoKTtcclxufVxyXG59IiwiPGRpdiBjbGFzcz1cIm5neC1lcnJvclwiICpuZ0lmPVwiZXJyb3JNZXNzYWdlXCI+XHJcbiAge3sgZXJyb3JNZXNzYWdlIH19XHJcbjwvZGl2PiJdfQ==
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import { NgModule } from '@angular/core';
|
|
2
2
|
import { NgxFormErrorsComponent } from './ngx-form-errors.component';
|
|
3
|
+
import { ErrorComponent } from './error/error.component';
|
|
3
4
|
import * as i0 from "@angular/core";
|
|
4
5
|
export class NgxFormErrorsModule {
|
|
5
6
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NgxFormErrorsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
6
|
-
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.14", ngImport: i0, type: NgxFormErrorsModule, imports: [NgxFormErrorsComponent], exports: [NgxFormErrorsComponent] });
|
|
7
|
-
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NgxFormErrorsModule });
|
|
7
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.14", ngImport: i0, type: NgxFormErrorsModule, imports: [NgxFormErrorsComponent, ErrorComponent], exports: [NgxFormErrorsComponent, ErrorComponent] });
|
|
8
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NgxFormErrorsModule, imports: [ErrorComponent] });
|
|
8
9
|
}
|
|
9
10
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NgxFormErrorsModule, decorators: [{
|
|
10
11
|
type: NgModule,
|
|
11
12
|
args: [{
|
|
12
|
-
imports: [NgxFormErrorsComponent], // 👈 standalone component import
|
|
13
|
-
exports: [NgxFormErrorsComponent] // 👈 expose to users
|
|
13
|
+
imports: [NgxFormErrorsComponent, ErrorComponent], // 👈 standalone component import
|
|
14
|
+
exports: [NgxFormErrorsComponent, ErrorComponent] // 👈 expose to users
|
|
14
15
|
}]
|
|
15
16
|
}] });
|
|
16
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
17
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmd4LWZvcm0tZXJyb3JzLm1vZHVsZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1mb3JtLWVycm9ycy9zcmMvbGliL25neC1mb3JtLWVycm9ycy5tb2R1bGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUN6QyxPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUNyRSxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0seUJBQXlCLENBQUM7O0FBTXpELE1BQU0sT0FBTyxtQkFBbUI7d0dBQW5CLG1CQUFtQjt5R0FBbkIsbUJBQW1CLFlBSHBCLHNCQUFzQixFQUFDLGNBQWMsYUFDckMsc0JBQXNCLEVBQUMsY0FBYzt5R0FFcEMsbUJBQW1CLFlBSEcsY0FBYzs7NEZBR3BDLG1CQUFtQjtrQkFKL0IsUUFBUTttQkFBQztvQkFDUixPQUFPLEVBQUUsQ0FBQyxzQkFBc0IsRUFBQyxjQUFjLENBQUMsRUFBSSxpQ0FBaUM7b0JBQ3JGLE9BQU8sRUFBRSxDQUFDLHNCQUFzQixFQUFDLGNBQWMsQ0FBQyxDQUFJLHFCQUFxQjtpQkFDMUUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBOZ01vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBOZ3hGb3JtRXJyb3JzQ29tcG9uZW50IH0gZnJvbSAnLi9uZ3gtZm9ybS1lcnJvcnMuY29tcG9uZW50JztcclxuaW1wb3J0IHsgRXJyb3JDb21wb25lbnQgfSBmcm9tICcuL2Vycm9yL2Vycm9yLmNvbXBvbmVudCc7XHJcblxyXG5ATmdNb2R1bGUoe1xyXG4gIGltcG9ydHM6IFtOZ3hGb3JtRXJyb3JzQ29tcG9uZW50LEVycm9yQ29tcG9uZW50XSwgICAvLyDwn5GIIHN0YW5kYWxvbmUgY29tcG9uZW50IGltcG9ydFxyXG4gIGV4cG9ydHM6IFtOZ3hGb3JtRXJyb3JzQ29tcG9uZW50LEVycm9yQ29tcG9uZW50XSAgICAvLyDwn5GIIGV4cG9zZSB0byB1c2Vyc1xyXG59KVxyXG5leHBvcnQgY2xhc3MgTmd4Rm9ybUVycm9yc01vZHVsZSB7fSJdfQ==
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Injectable } from '@angular/core';
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
export class ErrorService {
|
|
4
|
+
getErrorMessage(errors, label) {
|
|
5
|
+
if (errors['required']) {
|
|
6
|
+
return `${label} is required`;
|
|
7
|
+
}
|
|
8
|
+
if (errors['email']) {
|
|
9
|
+
return `Invalid email format`;
|
|
10
|
+
}
|
|
11
|
+
if (errors['minlength']) {
|
|
12
|
+
return `${label} must be at least ${errors['minlength'].requiredLength} characters`;
|
|
13
|
+
}
|
|
14
|
+
if (errors['maxlength']) {
|
|
15
|
+
return `${label} cannot exceed ${errors['maxlength'].requiredLength} characters`;
|
|
16
|
+
}
|
|
17
|
+
if (errors['pattern']) {
|
|
18
|
+
return `Invalid ${label} format`;
|
|
19
|
+
}
|
|
20
|
+
return `Invalid ${label}`;
|
|
21
|
+
}
|
|
22
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ErrorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
23
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ErrorService, providedIn: 'root' });
|
|
24
|
+
}
|
|
25
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ErrorService, decorators: [{
|
|
26
|
+
type: Injectable,
|
|
27
|
+
args: [{
|
|
28
|
+
providedIn: 'root'
|
|
29
|
+
}]
|
|
30
|
+
}] });
|
|
31
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXJyb3Iuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1mb3JtLWVycm9ycy9zcmMvbGliL3NlcnZpY2VzL2Vycm9yLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQzs7QUFLM0MsTUFBTSxPQUFPLFlBQVk7SUFFdkIsZUFBZSxDQUFDLE1BQVcsRUFBRSxLQUFhO1FBRXhDLElBQUksTUFBTSxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUM7WUFDdkIsT0FBTyxHQUFHLEtBQUssY0FBYyxDQUFDO1FBQ2hDLENBQUM7UUFFRCxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1lBQ3BCLE9BQU8sc0JBQXNCLENBQUM7UUFDaEMsQ0FBQztRQUVELElBQUksTUFBTSxDQUFDLFdBQVcsQ0FBQyxFQUFFLENBQUM7WUFDeEIsT0FBTyxHQUFHLEtBQUsscUJBQXFCLE1BQU0sQ0FBQyxXQUFXLENBQUMsQ0FBQyxjQUFjLGFBQWEsQ0FBQztRQUN0RixDQUFDO1FBRUQsSUFBSSxNQUFNLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQztZQUN4QixPQUFPLEdBQUcsS0FBSyxrQkFBa0IsTUFBTSxDQUFDLFdBQVcsQ0FBQyxDQUFDLGNBQWMsYUFBYSxDQUFDO1FBQ25GLENBQUM7UUFFRCxJQUFJLE1BQU0sQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDO1lBQ3RCLE9BQU8sV0FBVyxLQUFLLFNBQVMsQ0FBQztRQUNuQyxDQUFDO1FBRUQsT0FBTyxXQUFXLEtBQUssRUFBRSxDQUFDO0lBQzVCLENBQUM7d0dBekJVLFlBQVk7NEdBQVosWUFBWSxjQUZYLE1BQU07OzRGQUVQLFlBQVk7a0JBSHhCLFVBQVU7bUJBQUM7b0JBQ1YsVUFBVSxFQUFFLE1BQU07aUJBQ25CIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5cclxuQEluamVjdGFibGUoe1xyXG4gIHByb3ZpZGVkSW46ICdyb290J1xyXG59KVxyXG5leHBvcnQgY2xhc3MgRXJyb3JTZXJ2aWNlIHtcclxuXHJcbiAgZ2V0RXJyb3JNZXNzYWdlKGVycm9yczogYW55LCBsYWJlbDogc3RyaW5nKTogc3RyaW5nIHtcclxuXHJcbiAgICBpZiAoZXJyb3JzWydyZXF1aXJlZCddKSB7XHJcbiAgICAgIHJldHVybiBgJHtsYWJlbH0gaXMgcmVxdWlyZWRgO1xyXG4gICAgfVxyXG5cclxuICAgIGlmIChlcnJvcnNbJ2VtYWlsJ10pIHtcclxuICAgICAgcmV0dXJuIGBJbnZhbGlkIGVtYWlsIGZvcm1hdGA7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKGVycm9yc1snbWlubGVuZ3RoJ10pIHtcclxuICAgICAgcmV0dXJuIGAke2xhYmVsfSBtdXN0IGJlIGF0IGxlYXN0ICR7ZXJyb3JzWydtaW5sZW5ndGgnXS5yZXF1aXJlZExlbmd0aH0gY2hhcmFjdGVyc2A7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKGVycm9yc1snbWF4bGVuZ3RoJ10pIHtcclxuICAgICAgcmV0dXJuIGAke2xhYmVsfSBjYW5ub3QgZXhjZWVkICR7ZXJyb3JzWydtYXhsZW5ndGgnXS5yZXF1aXJlZExlbmd0aH0gY2hhcmFjdGVyc2A7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKGVycm9yc1sncGF0dGVybiddKSB7XHJcbiAgICAgIHJldHVybiBgSW52YWxpZCAke2xhYmVsfSBmb3JtYXRgO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBgSW52YWxpZCAke2xhYmVsfWA7XHJcbiAgfVxyXG5cclxufSJdfQ==
|
package/esm2022/public-api.mjs
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/*
|
|
2
2
|
* Public API Surface of ngx-form-errors
|
|
3
3
|
*/
|
|
4
|
-
export * from './lib/ngx-form-errors.service';
|
|
5
|
-
export * from './lib/ngx-form-errors.component';
|
|
6
4
|
export * from './lib/ngx-form-errors.module';
|
|
7
|
-
|
|
5
|
+
export * from './lib/ngx-form-errors.component';
|
|
6
|
+
export * from './lib/error/error.component';
|
|
7
|
+
export * from './lib/services/error.service';
|
|
8
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHVibGljLWFwaS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Byb2plY3RzL25neC1mb3JtLWVycm9ycy9zcmMvcHVibGljLWFwaS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7R0FFRztBQUVILGNBQWMsOEJBQThCLENBQUM7QUFDN0MsY0FBYyxpQ0FBaUMsQ0FBQztBQUNoRCxjQUFjLDZCQUE2QixDQUFDO0FBQzVDLGNBQWMsOEJBQThCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxyXG4gKiBQdWJsaWMgQVBJIFN1cmZhY2Ugb2Ygbmd4LWZvcm0tZXJyb3JzXHJcbiAqL1xyXG5cclxuZXhwb3J0ICogZnJvbSAnLi9saWIvbmd4LWZvcm0tZXJyb3JzLm1vZHVsZSc7XHJcbmV4cG9ydCAqIGZyb20gJy4vbGliL25neC1mb3JtLWVycm9ycy5jb21wb25lbnQnO1xyXG5leHBvcnQgKiBmcm9tICcuL2xpYi9lcnJvci9lcnJvci5jb21wb25lbnQnO1xyXG5leHBvcnQgKiBmcm9tICcuL2xpYi9zZXJ2aWNlcy9lcnJvci5zZXJ2aWNlJzsiXX0=
|
|
@@ -1,17 +1,10 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { Injectable,
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
}
|
|
9
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NgxFormErrorsService, decorators: [{
|
|
10
|
-
type: Injectable,
|
|
11
|
-
args: [{
|
|
12
|
-
providedIn: 'root'
|
|
13
|
-
}]
|
|
14
|
-
}], ctorParameters: () => [] });
|
|
2
|
+
import { Component, Injectable, Input, NgModule } from '@angular/core';
|
|
3
|
+
import * as i1 from '@angular/forms';
|
|
4
|
+
import { ReactiveFormsModule } from '@angular/forms';
|
|
5
|
+
import * as i3 from '@angular/common';
|
|
6
|
+
import { CommonModule } from '@angular/common';
|
|
7
|
+
import { Subject, takeUntil } from 'rxjs';
|
|
15
8
|
|
|
16
9
|
class NgxFormErrorsComponent {
|
|
17
10
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NgxFormErrorsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
@@ -30,16 +23,88 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
30
23
|
` }]
|
|
31
24
|
}] });
|
|
32
25
|
|
|
26
|
+
class ErrorService {
|
|
27
|
+
getErrorMessage(errors, label) {
|
|
28
|
+
if (errors['required']) {
|
|
29
|
+
return `${label} is required`;
|
|
30
|
+
}
|
|
31
|
+
if (errors['email']) {
|
|
32
|
+
return `Invalid email format`;
|
|
33
|
+
}
|
|
34
|
+
if (errors['minlength']) {
|
|
35
|
+
return `${label} must be at least ${errors['minlength'].requiredLength} characters`;
|
|
36
|
+
}
|
|
37
|
+
if (errors['maxlength']) {
|
|
38
|
+
return `${label} cannot exceed ${errors['maxlength'].requiredLength} characters`;
|
|
39
|
+
}
|
|
40
|
+
if (errors['pattern']) {
|
|
41
|
+
return `Invalid ${label} format`;
|
|
42
|
+
}
|
|
43
|
+
return `Invalid ${label}`;
|
|
44
|
+
}
|
|
45
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ErrorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
46
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ErrorService, providedIn: 'root' });
|
|
47
|
+
}
|
|
48
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ErrorService, decorators: [{
|
|
49
|
+
type: Injectable,
|
|
50
|
+
args: [{
|
|
51
|
+
providedIn: 'root'
|
|
52
|
+
}]
|
|
53
|
+
}] });
|
|
54
|
+
|
|
55
|
+
class ErrorComponent {
|
|
56
|
+
controlContainer;
|
|
57
|
+
errorService;
|
|
58
|
+
destroy$ = new Subject();
|
|
59
|
+
field;
|
|
60
|
+
label;
|
|
61
|
+
form;
|
|
62
|
+
errorMessage = '';
|
|
63
|
+
constructor(controlContainer, errorService) {
|
|
64
|
+
this.controlContainer = controlContainer;
|
|
65
|
+
this.errorService = errorService;
|
|
66
|
+
}
|
|
67
|
+
ngOnInit() {
|
|
68
|
+
this.form = this.controlContainer.control;
|
|
69
|
+
const control = this.form.get(this.field);
|
|
70
|
+
if (!control)
|
|
71
|
+
return;
|
|
72
|
+
control.statusChanges.pipe(takeUntil(this.destroy$))
|
|
73
|
+
.subscribe(() => {
|
|
74
|
+
if (control.errors && (control.touched || control.dirty)) {
|
|
75
|
+
this.errorMessage = this.errorService.getErrorMessage(control.errors, this.label || this.field);
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
this.errorMessage = '';
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
ngOnDestroy() {
|
|
83
|
+
this.destroy$.next();
|
|
84
|
+
this.destroy$.complete();
|
|
85
|
+
}
|
|
86
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ErrorComponent, deps: [{ token: i1.ControlContainer }, { token: ErrorService }], target: i0.ɵɵFactoryTarget.Component });
|
|
87
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: ErrorComponent, isStandalone: true, selector: "ngx-error", inputs: { field: "field", label: "label" }, ngImport: i0, template: "<div class=\"ngx-error\" *ngIf=\"errorMessage\">\r\n {{ errorMessage }}\r\n</div>", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }] });
|
|
88
|
+
}
|
|
89
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ErrorComponent, decorators: [{
|
|
90
|
+
type: Component,
|
|
91
|
+
args: [{ selector: 'ngx-error', standalone: true, imports: [CommonModule, ReactiveFormsModule], template: "<div class=\"ngx-error\" *ngIf=\"errorMessage\">\r\n {{ errorMessage }}\r\n</div>" }]
|
|
92
|
+
}], ctorParameters: () => [{ type: i1.ControlContainer }, { type: ErrorService }], propDecorators: { field: [{
|
|
93
|
+
type: Input
|
|
94
|
+
}], label: [{
|
|
95
|
+
type: Input
|
|
96
|
+
}] } });
|
|
97
|
+
|
|
33
98
|
class NgxFormErrorsModule {
|
|
34
99
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NgxFormErrorsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
35
|
-
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.14", ngImport: i0, type: NgxFormErrorsModule, imports: [NgxFormErrorsComponent], exports: [NgxFormErrorsComponent] });
|
|
36
|
-
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NgxFormErrorsModule });
|
|
100
|
+
static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.14", ngImport: i0, type: NgxFormErrorsModule, imports: [NgxFormErrorsComponent, ErrorComponent], exports: [NgxFormErrorsComponent, ErrorComponent] });
|
|
101
|
+
static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NgxFormErrorsModule, imports: [ErrorComponent] });
|
|
37
102
|
}
|
|
38
103
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NgxFormErrorsModule, decorators: [{
|
|
39
104
|
type: NgModule,
|
|
40
105
|
args: [{
|
|
41
|
-
imports: [NgxFormErrorsComponent], // 👈 standalone component import
|
|
42
|
-
exports: [NgxFormErrorsComponent] // 👈 expose to users
|
|
106
|
+
imports: [NgxFormErrorsComponent, ErrorComponent], // 👈 standalone component import
|
|
107
|
+
exports: [NgxFormErrorsComponent, ErrorComponent] // 👈 expose to users
|
|
43
108
|
}]
|
|
44
109
|
}] });
|
|
45
110
|
|
|
@@ -51,5 +116,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
51
116
|
* Generated bundle index. Do not edit.
|
|
52
117
|
*/
|
|
53
118
|
|
|
54
|
-
export { NgxFormErrorsComponent, NgxFormErrorsModule
|
|
119
|
+
export { ErrorComponent, ErrorService, NgxFormErrorsComponent, NgxFormErrorsModule };
|
|
55
120
|
//# sourceMappingURL=ngx-mat-form-errors.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ngx-mat-form-errors.mjs","sources":["../../../projects/ngx-form-errors/src/lib/ngx-form-errors.
|
|
1
|
+
{"version":3,"file":"ngx-mat-form-errors.mjs","sources":["../../../projects/ngx-form-errors/src/lib/ngx-form-errors.component.ts","../../../projects/ngx-form-errors/src/lib/services/error.service.ts","../../../projects/ngx-form-errors/src/lib/error/error.component.ts","../../../projects/ngx-form-errors/src/lib/error/error.component.html","../../../projects/ngx-form-errors/src/lib/ngx-form-errors.module.ts","../../../projects/ngx-form-errors/src/public-api.ts","../../../projects/ngx-form-errors/src/ngx-mat-form-errors.ts"],"sourcesContent":["import { Component } from '@angular/core';\r\n\r\n@Component({\r\n selector: 'lib-ngx-form-errors',\r\n standalone: true,\r\n imports: [],\r\n template: `\r\n <p>\r\n ngx-form-errors works!\r\n </p>\r\n `,\r\n styles: ``\r\n})\r\nexport class NgxFormErrorsComponent {\r\n\r\n}\r\n","import { Injectable } from '@angular/core';\r\n\r\n@Injectable({\r\n providedIn: 'root'\r\n})\r\nexport class ErrorService {\r\n\r\n getErrorMessage(errors: any, label: string): string {\r\n\r\n if (errors['required']) {\r\n return `${label} is required`;\r\n }\r\n\r\n if (errors['email']) {\r\n return `Invalid email format`;\r\n }\r\n\r\n if (errors['minlength']) {\r\n return `${label} must be at least ${errors['minlength'].requiredLength} characters`;\r\n }\r\n\r\n if (errors['maxlength']) {\r\n return `${label} cannot exceed ${errors['maxlength'].requiredLength} characters`;\r\n }\r\n\r\n if (errors['pattern']) {\r\n return `Invalid ${label} format`;\r\n }\r\n\r\n return `Invalid ${label}`;\r\n }\r\n\r\n}","import { Component, Input, OnInit } from '@angular/core';\r\nimport { ControlContainer, FormGroup, ReactiveFormsModule } from '@angular/forms';\r\nimport { CommonModule } from '@angular/common';\r\nimport { ErrorService } from '../services/error.service';\r\nimport { Subject, takeUntil } from 'rxjs';\r\n\r\n\r\n@Component({\r\n selector: 'ngx-error',\r\n standalone: true,\r\n imports: [CommonModule, ReactiveFormsModule],\r\n templateUrl: './error.component.html'\r\n})\r\nexport class ErrorComponent implements OnInit {\r\n\r\n destroy$ = new Subject<void>();\r\n @Input() field!: string;\r\n @Input() label?: string;\r\n\r\n form!: FormGroup;\r\n errorMessage = '';\r\n\r\n constructor(\r\n private controlContainer: ControlContainer,\r\n private errorService: ErrorService\r\n ) {}\r\n\r\n ngOnInit() {\r\n this.form = this.controlContainer.control as FormGroup;\r\n\r\n const control = this.form.get(this.field);\r\n if (!control) return;\r\n\r\n control.statusChanges.pipe(takeUntil(this.destroy$))\r\n.subscribe(() => {\r\n if (control.errors && (control.touched || control.dirty)) {\r\n this.errorMessage = this.errorService.getErrorMessage(\r\n control.errors,\r\n this.label || this.field\r\n );\r\n } else {\r\n this.errorMessage = '';\r\n }\r\n });\r\n }\r\n\r\n ngOnDestroy() {\r\n this.destroy$.next();\r\n this.destroy$.complete();\r\n}\r\n}","<div class=\"ngx-error\" *ngIf=\"errorMessage\">\r\n {{ errorMessage }}\r\n</div>","import { NgModule } from '@angular/core';\r\nimport { NgxFormErrorsComponent } from './ngx-form-errors.component';\r\nimport { ErrorComponent } from './error/error.component';\r\n\r\n@NgModule({\r\n imports: [NgxFormErrorsComponent,ErrorComponent], // 👈 standalone component import\r\n exports: [NgxFormErrorsComponent,ErrorComponent] // 👈 expose to users\r\n})\r\nexport class NgxFormErrorsModule {}","/*\r\n * Public API Surface of ngx-form-errors\r\n */\r\n\r\nexport * from './lib/ngx-form-errors.module';\r\nexport * from './lib/ngx-form-errors.component';\r\nexport * from './lib/error/error.component';\r\nexport * from './lib/services/error.service';","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":["i2.ErrorService"],"mappings":";;;;;;;;MAaa,sBAAsB,CAAA;wGAAtB,sBAAsB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA,CAAA;AAAtB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,sBAAsB,EAPvB,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,qBAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAAA,CAAA;;;;AAIT,EAAA,CAAA,EAAA,QAAA,EAAA,IAAA,EAAA,MAAA,EAAA,CAAA,EAAA,CAAA,EAAA,CAAA,CAAA;;4FAGU,sBAAsB,EAAA,UAAA,EAAA,CAAA;kBAXlC,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,qBAAqB,EACnB,UAAA,EAAA,IAAI,EACP,OAAA,EAAA,EAAE,EACD,QAAA,EAAA,CAAA;;;;AAIT,EAAA,CAAA,EAAA,CAAA;;;MCLU,YAAY,CAAA;IAEvB,eAAe,CAAC,MAAW,EAAE,KAAa,EAAA;AAExC,QAAA,IAAI,MAAM,CAAC,UAAU,CAAC,EAAE;YACtB,OAAO,CAAA,EAAG,KAAK,CAAA,YAAA,CAAc,CAAC;SAC/B;AAED,QAAA,IAAI,MAAM,CAAC,OAAO,CAAC,EAAE;AACnB,YAAA,OAAO,sBAAsB,CAAC;SAC/B;AAED,QAAA,IAAI,MAAM,CAAC,WAAW,CAAC,EAAE;YACvB,OAAO,CAAA,EAAG,KAAK,CAAA,kBAAA,EAAqB,MAAM,CAAC,WAAW,CAAC,CAAC,cAAc,CAAA,WAAA,CAAa,CAAC;SACrF;AAED,QAAA,IAAI,MAAM,CAAC,WAAW,CAAC,EAAE;YACvB,OAAO,CAAA,EAAG,KAAK,CAAA,eAAA,EAAkB,MAAM,CAAC,WAAW,CAAC,CAAC,cAAc,CAAA,WAAA,CAAa,CAAC;SAClF;AAED,QAAA,IAAI,MAAM,CAAC,SAAS,CAAC,EAAE;YACrB,OAAO,CAAA,QAAA,EAAW,KAAK,CAAA,OAAA,CAAS,CAAC;SAClC;QAED,OAAO,CAAA,QAAA,EAAW,KAAK,CAAA,CAAE,CAAC;KAC3B;wGAzBU,YAAY,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,UAAA,EAAA,CAAA,CAAA;AAAZ,IAAA,OAAA,KAAA,GAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,YAAY,cAFX,MAAM,EAAA,CAAA,CAAA;;4FAEP,YAAY,EAAA,UAAA,EAAA,CAAA;kBAHxB,UAAU;AAAC,YAAA,IAAA,EAAA,CAAA;AACV,oBAAA,UAAU,EAAE,MAAM;AACnB,iBAAA,CAAA;;;MCSY,cAAc,CAAA;AAUf,IAAA,gBAAA,CAAA;AACA,IAAA,YAAA,CAAA;AATX,IAAA,QAAQ,GAAG,IAAI,OAAO,EAAQ,CAAC;AACrB,IAAA,KAAK,CAAU;AACf,IAAA,KAAK,CAAU;AAExB,IAAA,IAAI,CAAa;IACjB,YAAY,GAAG,EAAE,CAAC;IAElB,WACU,CAAA,gBAAkC,EAClC,YAA0B,EAAA;QAD1B,IAAgB,CAAA,gBAAA,GAAhB,gBAAgB,CAAkB;QAClC,IAAY,CAAA,YAAA,GAAZ,YAAY,CAAc;KAChC;IAEJ,QAAQ,GAAA;QACN,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,gBAAgB,CAAC,OAAoB,CAAC;AAEvD,QAAA,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC1C,QAAA,IAAI,CAAC,OAAO;YAAE,OAAO;QAErB,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;aACvD,SAAS,CAAC,MAAK;AACV,YAAA,IAAI,OAAO,CAAC,MAAM,KAAK,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,KAAK,CAAC,EAAE;gBACxD,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC,eAAe,CACnD,OAAO,CAAC,MAAM,EACd,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,CACzB,CAAC;aACH;iBAAM;AACL,gBAAA,IAAI,CAAC,YAAY,GAAG,EAAE,CAAC;aACxB;AACH,SAAC,CAAC,CAAC;KACJ;IAED,WAAW,GAAA;AACX,QAAA,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;AACrB,QAAA,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC;KAC1B;wGApCY,cAAc,EAAA,IAAA,EAAA,CAAA,EAAA,KAAA,EAAA,EAAA,CAAA,gBAAA,EAAA,EAAA,EAAA,KAAA,EAAAA,YAAA,EAAA,CAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,SAAA,EAAA,CAAA,CAAA;AAAd,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,oBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,IAAA,EAAA,cAAc,ECb3B,YAAA,EAAA,IAAA,EAAA,QAAA,EAAA,WAAA,EAAA,MAAA,EAAA,EAAA,KAAA,EAAA,OAAA,EAAA,KAAA,EAAA,OAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,EAAA,oFAEM,EDQM,YAAA,EAAA,CAAA,EAAA,IAAA,EAAA,UAAA,EAAA,IAAA,EAAA,YAAY,kIAAE,mBAAmB,EAAA,CAAA,EAAA,CAAA,CAAA;;4FAGhC,cAAc,EAAA,UAAA,EAAA,CAAA;kBAN1B,SAAS;AACE,YAAA,IAAA,EAAA,CAAA,EAAA,QAAA,EAAA,WAAW,cACT,IAAI,EAAA,OAAA,EACP,CAAC,YAAY,EAAE,mBAAmB,CAAC,EAAA,QAAA,EAAA,oFAAA,EAAA,CAAA;6GAMnC,KAAK,EAAA,CAAA;sBAAb,KAAK;gBACG,KAAK,EAAA,CAAA;sBAAb,KAAK;;;METK,mBAAmB,CAAA;wGAAnB,mBAAmB,EAAA,IAAA,EAAA,EAAA,EAAA,MAAA,EAAA,EAAA,CAAA,eAAA,CAAA,QAAA,EAAA,CAAA,CAAA;AAAnB,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,mBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,mBAAmB,YAHpB,sBAAsB,EAAC,cAAc,CACrC,EAAA,OAAA,EAAA,CAAA,sBAAsB,EAAC,cAAc,CAAA,EAAA,CAAA,CAAA;AAEpC,IAAA,OAAA,IAAA,GAAA,EAAA,CAAA,mBAAA,CAAA,EAAA,UAAA,EAAA,QAAA,EAAA,OAAA,EAAA,SAAA,EAAA,QAAA,EAAA,EAAA,EAAA,IAAA,EAAA,mBAAmB,YAHG,cAAc,CAAA,EAAA,CAAA,CAAA;;4FAGpC,mBAAmB,EAAA,UAAA,EAAA,CAAA;kBAJ/B,QAAQ;AAAC,YAAA,IAAA,EAAA,CAAA;AACR,oBAAA,OAAO,EAAE,CAAC,sBAAsB,EAAC,cAAc,CAAC;AAChD,oBAAA,OAAO,EAAE,CAAC,sBAAsB,EAAC,cAAc,CAAC;AACjD,iBAAA,CAAA;;;ACPD;;AAEG;;ACFH;;AAEG;;;;"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { OnInit } from '@angular/core';
|
|
2
|
+
import { ControlContainer, FormGroup } from '@angular/forms';
|
|
3
|
+
import { ErrorService } from '../services/error.service';
|
|
4
|
+
import { Subject } from 'rxjs';
|
|
5
|
+
import * as i0 from "@angular/core";
|
|
6
|
+
export declare class ErrorComponent implements OnInit {
|
|
7
|
+
private controlContainer;
|
|
8
|
+
private errorService;
|
|
9
|
+
destroy$: Subject<void>;
|
|
10
|
+
field: string;
|
|
11
|
+
label?: string;
|
|
12
|
+
form: FormGroup;
|
|
13
|
+
errorMessage: string;
|
|
14
|
+
constructor(controlContainer: ControlContainer, errorService: ErrorService);
|
|
15
|
+
ngOnInit(): void;
|
|
16
|
+
ngOnDestroy(): void;
|
|
17
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<ErrorComponent, never>;
|
|
18
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<ErrorComponent, "ngx-error", never, { "field": { "alias": "field"; "required": false; }; "label": { "alias": "label"; "required": false; }; }, {}, never, never, true, never>;
|
|
19
|
+
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import * as i0 from "@angular/core";
|
|
2
2
|
import * as i1 from "./ngx-form-errors.component";
|
|
3
|
+
import * as i2 from "./error/error.component";
|
|
3
4
|
export declare class NgxFormErrorsModule {
|
|
4
5
|
static ɵfac: i0.ɵɵFactoryDeclaration<NgxFormErrorsModule, never>;
|
|
5
|
-
static ɵmod: i0.ɵɵNgModuleDeclaration<NgxFormErrorsModule, never, [typeof i1.NgxFormErrorsComponent], [typeof i1.NgxFormErrorsComponent]>;
|
|
6
|
+
static ɵmod: i0.ɵɵNgModuleDeclaration<NgxFormErrorsModule, never, [typeof i1.NgxFormErrorsComponent, typeof i2.ErrorComponent], [typeof i1.NgxFormErrorsComponent, typeof i2.ErrorComponent]>;
|
|
6
7
|
static ɵinj: i0.ɵɵInjectorDeclaration<NgxFormErrorsModule>;
|
|
7
8
|
}
|
package/package.json
CHANGED
package/public-api.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
export * from './lib/ngx-form-errors.service';
|
|
2
|
-
export * from './lib/ngx-form-errors.component';
|
|
3
1
|
export * from './lib/ngx-form-errors.module';
|
|
2
|
+
export * from './lib/ngx-form-errors.component';
|
|
3
|
+
export * from './lib/error/error.component';
|
|
4
|
+
export * from './lib/services/error.service';
|