+
Min-length is {{ myError.getError('minlength')?.requiredLength }}
-
+
Max-length is {{ myError.getError('maxlength')?.requiredLength }}
diff --git a/src/ngxerrors.directive.ts b/src/ngxerrors.directive.ts
index 4854f0b..9e1f577 100755
--- a/src/ngxerrors.directive.ts
+++ b/src/ngxerrors.directive.ts
@@ -1,4 +1,4 @@
-import { Directive, Input, OnChanges, AfterViewInit, SimpleChanges } from '@angular/core';
+import { Directive, Input, OnChanges, OnDestroy, AfterViewInit } from '@angular/core';
import { FormGroupDirective, AbstractControl } from '@angular/forms';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
@@ -13,7 +13,7 @@ import { toArray } from './utils/toArray';
selector: '[ngxErrors]',
exportAs: 'ngxErrors'
})
-export class NgxErrorsDirective implements OnChanges, AfterViewInit {
+export class NgxErrorsDirective implements OnChanges, OnDestroy, AfterViewInit {
@Input('ngxErrors')
controlName: string;
@@ -23,10 +23,10 @@ export class NgxErrorsDirective implements OnChanges, AfterViewInit {
control: AbstractControl;
ready: boolean = false;
-
+
constructor(
private form: FormGroupDirective
- ) {}
+ ) { }
get errors() {
if (!this.ready) return;
@@ -37,17 +37,12 @@ export class NgxErrorsDirective implements OnChanges, AfterViewInit {
return !!this.errors;
}
- checkControlProps(props: ErrorOptions) {
- return !props ? true : toArray(props).every((prop: string) => this.control[prop]);
- }
-
hasError(name: string, conditions: ErrorOptions): boolean {
- if (!this.ready) return;
- const controlPropsState = this.checkControlProps(conditions);
- if (name.charAt(0) === '*') {
- return this.control.invalid && controlPropsState;
- }
- return this.control.hasError(name) && controlPropsState;
+ return this.checkPropState('invalid', name, conditions);
+ }
+
+ isValid(name: string, conditions: ErrorOptions): boolean {
+ return this.checkPropState('valid', name, conditions);
}
getError(name: string) {
@@ -55,6 +50,33 @@ export class NgxErrorsDirective implements OnChanges, AfterViewInit {
return this.control.getError(name);
}
+ private checkPropState(prop: string, name: string, conditions: ErrorOptions): boolean {
+ if (!this.ready) return;
+ const controlPropsState = (
+ !conditions || toArray(conditions).every((condition: string) => this.control[condition])
+ );
+ if (name.charAt(0) === '*') {
+ return this.control[prop] && controlPropsState;
+ }
+ return (
+ prop === 'valid' ? !this.control.hasError(name) : this.control.hasError(name) && controlPropsState
+ );
+ }
+
+ private checkStatus() {
+ const control = this.control;
+ const errors = control.errors;
+ this.ready = true;
+ if (!errors) return;
+ for (const errorName in errors) {
+ this.subject.next({ control, errorName });
+ }
+ }
+
+ ngOnChanges() {
+ this.control = this.form.control.get(this.controlName);
+ }
+
ngAfterViewInit() {
setTimeout(() => {
this.checkStatus();
@@ -62,17 +84,8 @@ export class NgxErrorsDirective implements OnChanges, AfterViewInit {
});
}
- ngOnChanges(changes: SimpleChanges) {
- this.control = this.form.control.get(changes.controlName.currentValue);
- }
-
- checkStatus() {
- const errors = this.control.errors;
- this.ready = true;
- if (!errors) return;
- for (const error in errors) {
- this.subject.next({ control: this.control, errorName: error });
- }
+ ngOnDestroy() {
+ this.subject.unsubscribe();
}
}
\ No newline at end of file
diff --git a/src/test/ngxerrors.spec.ts b/src/test/ngxerrors.spec.ts
index 35668cf..c0149ae 100755
--- a/src/test/ngxerrors.spec.ts
+++ b/src/test/ngxerrors.spec.ts
@@ -28,6 +28,8 @@ TestBed.initTestEnvironment(
{{ prop.errors | json }}
{{ prop.hasErrors | json }}
+
{{ prop.isValid('*', ['dirty']) | json }}
+
{{ prop.isValid('required', ['dirty']) | json }}
@@ -136,6 +138,9 @@ describe('Directives: ngxErrors, ngxError, when', () => {
});
it('should provide a template ref API via ngxErrors exportAs', async (done) => {
+
+ const parse = (name) => JSON.parse(el.query(By.css(name)).nativeElement.textContent);
+
await fixture.whenStable();
fixture.changeDetectorRef.markForCheck();
@@ -146,6 +151,8 @@ describe('Directives: ngxErrors, ngxError, when', () => {
expect(element.nativeElement.classList.contains('requiredVisibleAtRuntime')).toBe(true);
expect(element.nativeElement.classList.contains('requiredVisibleWhenDirty')).toBe(false);
expect(element.nativeElement.classList.contains('requiredVisibleWhenDirtyTouched')).toBe(false);
+ expect(parse('.errorProp3')).toBe(false);
+ expect(parse('.errorProp4')).toBe(false);
component.form.patchValue({ prop: 'ngxErrors' });
component.form.get('prop').markAsDirty();
@@ -154,12 +161,16 @@ describe('Directives: ngxErrors, ngxError, when', () => {
await fixture.whenStable();
expect(component.form.get('prop').dirty).toBe(true);
expect(component.form.get('prop').touched).toBe(true);
+ expect(parse('.errorProp3')).toBe(true);
+ expect(parse('.errorProp4')).toBe(true);
expect(element.nativeElement.classList.contains('requiredVisibleAtRuntime')).toBe(false);
component.form.patchValue({ prop: '' });
fixture.detectChanges();
await fixture.whenStable();
expect(element.nativeElement.classList.contains('requiredVisibleWhenDirty')).toBe(true);
expect(element.nativeElement.classList.contains('requiredVisibleWhenDirtyTouched')).toBe(true);
+ expect(parse('.errorProp3')).toBe(false);
+ expect(parse('.errorProp4')).toBe(false);
component.form.patchValue({ prop: 'ngx' });
fixture.detectChanges();
@@ -172,6 +183,8 @@ describe('Directives: ngxErrors, ngxError, when', () => {
expect(component.form.get('prop').hasError('minlength')).toBe(true);
expect(component.form.get('prop').hasError('maxlength')).toBe(false);
expect(el.query(By.css('.errorMinLength')).nativeElement.textContent).toContain('5 characters minimum');
+ expect(parse('.errorProp3')).toBe(false);
+ expect(parse('.errorProp4')).toBe(true);
component.form.patchValue({ prop: 'ngxErrors!!!!!' });
fixture.detectChanges();
@@ -184,12 +197,12 @@ describe('Directives: ngxErrors, ngxError, when', () => {
expect(component.form.get('prop').hasError('minlength')).toBe(false);
expect(component.form.get('prop').hasError('maxlength')).toBe(true);
expect(el.query(By.css('.errorMinLength')).nativeElement.textContent).toContain('10 characters maximum');
-
- const parse = (name) => JSON.parse(el.query(By.css(name)).nativeElement.textContent);
expect(parse('.errorProp1').maxlength.requiredLength).toBe(10);
expect(parse('.errorProp1').maxlength.actualLength).toBe(14);
expect(parse('.errorProp2')).toBe(true);
+ expect(parse('.errorProp3')).toBe(false);
+ expect(parse('.errorProp4')).toBe(true);
done();