= EMPTY;
if (!this.controlErrorsClass || this.controlErrorsClass?.length === 0) {
if (this.mergedConfig.controlErrorsClass && this.mergedConfig.controlErrorsClass) {
@@ -118,6 +123,11 @@ export class ControlErrorsDirective implements OnInit, OnDestroy {
changesOnStatusChange$ = statusChanges$;
}
+ if (this.mergedConfig.controlErrorsOn.touched) {
+ // every time the touched property changes, skipping the first emission since it's the initial state
+ changesOnTouched$ = this.touchedChanges$.asObservable().pipe(distinctUntilChanged(), skip(1));
+ }
+
if (this.isInput && this.mergedConfig.controlErrorsOn.blur) {
const blur$ = fromEvent(this.host, 'focusout');
// blurFirstThenUponChange
@@ -144,12 +154,30 @@ export class ControlErrorsDirective implements OnInit, OnDestroy {
.pipe(takeUntil(this.destroy))
.subscribe(() => {
const hasErrors = !!this.control.errors;
+
if (hasErrors) {
this.showError();
} else {
this.hideError();
}
});
+
+ changesOnTouched$.pipe(takeUntil(this.destroy)).subscribe(() => {
+ const hasErrors = !!this.control.errors;
+ const touched = this.mergedConfig.controlErrorsOn.touched ? this.control.touched : true;
+
+ if (hasErrors && touched) {
+ this.showError();
+ } else {
+ this.hideError();
+ }
+ });
+ }
+
+ ngDoCheck(): void {
+ if (this.mergedConfig.controlErrorsOn.touched) {
+ this.touchedChanges$.next(this.control.touched);
+ }
}
private setError(text: string, error?: ValidationErrors) {
@@ -260,6 +288,7 @@ export class ControlErrorsDirective implements OnInit, OnDestroy {
blur: this.controlErrorsOnBlur ?? this.config.controlErrorsOn?.blur ?? true,
change: this.controlErrorsOnChange ?? this.config.controlErrorsOn?.change ?? false,
status: this.controlErrorsOnStatusChange ?? this.config.controlErrorsOn?.status ?? false,
+ touched: this.controlErrorsOnTouched ?? this.config.controlErrorsOn?.touched ?? false,
},
};
}
diff --git a/projects/ngneat/error-tailor/src/lib/error-tailor.providers.ts b/projects/ngneat/error-tailor/src/lib/error-tailor.providers.ts
index 8791ada..058a517 100644
--- a/projects/ngneat/error-tailor/src/lib/error-tailor.providers.ts
+++ b/projects/ngneat/error-tailor/src/lib/error-tailor.providers.ts
@@ -32,6 +32,7 @@ export type ErrorTailorConfig = {
blur?: boolean;
change?: boolean;
status?: boolean;
+ touched?: boolean;
};
};
diff --git a/src/app/app.component.html b/src/app/app.component.html
index 709d0a5..b00d8cc 100644
--- a/src/app/app.component.html
+++ b/src/app/app.component.html
@@ -1,6 +1,6 @@
Template
diff --git a/src/app/app.component.ts b/src/app/app.component.ts
index a76aa5c..fab8a69 100644
--- a/src/app/app.component.ts
+++ b/src/app/app.component.ts
@@ -6,7 +6,7 @@ import { ControlErrorsDirective } from '@ngneat/error-tailor';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
- styleUrls: ['./app.component.scss']
+ styleUrls: ['./app.component.scss'],
})
export class AppComponent {
form: UntypedFormGroup;
@@ -14,19 +14,19 @@ export class AppComponent {
options = Array.from(Array(5), (_, i) => ({
label: `Animal ${i + 1}`,
- id: i + 1
+ id: i + 1,
}));
extraErrors = {
minlength: ({ requiredLength }) => `Use country abbreviation! (min ${requiredLength} chars)`,
- maxlength: 'Use country abbreviation! (max 3 chars)'
+ maxlength: 'Use country abbreviation! (max 3 chars)',
};
@ViewChild('gdprErrorTailor', { static: true }) gdprErrorTailor: ControlErrorsDirective;
formGroup = this.builder.group({
name: [null, Validators.required],
- emailAddresses: this.builder.array([this.initEmailAddressFields()])
+ emailAddresses: this.builder.array([this.initEmailAddressFields()]),
});
get emailAddresses() {
@@ -36,7 +36,7 @@ export class AppComponent {
initEmailAddressFields(): UntypedFormGroup {
return this.builder.group({
label: [null, Validators.required],
- emailAddress: [null, [Validators.required, Validators.email]]
+ emailAddress: [null, [Validators.required, Validators.email]],
});
}
@@ -62,11 +62,11 @@ export class AppComponent {
address: this.builder.group(
{
city: ['', Validators.required],
- country: ['', [Validators.minLength(2), Validators.maxLength(3)]]
+ country: ['', [Validators.minLength(2), Validators.maxLength(3)]],
},
- { validator: addressValidator }
+ { validator: addressValidator },
),
- gdpr: [false, Validators.requiredTrue]
+ gdpr: [false, Validators.requiredTrue],
});
/**
* It's not necessary to set errors directly. It's done via the validator itself.
@@ -84,6 +84,14 @@ export class AppComponent {
this.gdprErrorTailor.hideError();
}
+ markNameAsTouched(): void {
+ this.form.controls.name.markAsTouched();
+ }
+
+ markNameAsUntouched(): void {
+ this.form.controls.name.markAsUntouched();
+ }
+
submit() {}
}