Skip to content

Instantly share code, notes, and snippets.

@jsdevtom
Last active February 6, 2021 13:09
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jsdevtom/5589af349a395b37e699b67417ef025b to your computer and use it in GitHub Desktop.
Save jsdevtom/5589af349a395b37e699b67417ef025b to your computer and use it in GitHub Desktop.
Angular 2 4 5 6 +: Find out if FormControl has required validator with Angular Material example.

Although this pipe is impure, it uses a "Blazing fast" hash in order to check if the AbstractControl has changed at all before calculating whether or not the AbstractControl has a required field.

You will need to install hash-sum like so:

npm i -S hash-sum
import { Pipe, PipeTransform } from '@angular/core';
import { hasRequiredField } from '@app/shared/utils/forms/has-required-field/has-required-field';
import { AbstractControl } from '@angular/forms';
import * as hashSum from 'hash-sum';
@Pipe({
name: 'hasRequiredField',
pure: false,
})
export class HasRequiredFieldPipe implements PipeTransform {
cachedControlHash: string = null;
cachedResult: boolean = null;
transform(control: AbstractControl): boolean {
const newHashOfControl = hashSum(control);
if (newHashOfControl !== this.cachedControlHash) {
const nowHasRequiredField = hasRequiredField(control);
this.cachedControlHash = hashSum(control);
this.cachedResult = nowHasRequiredField;
return nowHasRequiredField;
}
return this.cachedResult;
}
}
import { hasRequiredField } from '@app/shared/utils/forms/has-required-field';
import { FormControl, FormGroup, Validators } from '@angular/forms';
describe('hasRequiredField()', () => {
it('should return false if passed in anything other than AbstractControl', () => {
const notAbstractControl = [
null,
undefined,
1,
'hi',
() => {},
new Proxy({}, {}),
NaN,
Infinity,
];
notAbstractControl.forEach(value => {
expect(hasRequiredField(<any>value)).toBe(false);
});
});
it('should return false if passed in control without any validators', () => {
expect(hasRequiredField(new FormControl(''))).toBe(false);
});
it('should return false if passed in group without any validators', () => {
const formGroup = new FormGroup({
hi: new FormControl(''),
});
expect(hasRequiredField(formGroup)).toBe(false);
});
it('should return false if passed in control without required validator', () => {
expect(hasRequiredField(new FormControl('', Validators.max(5)))).toBe(
false,
);
});
it('should return false if passed in group without required validators', () => {
const formGroup = new FormGroup({
hi: new FormControl('', Validators.max(5)),
});
expect(hasRequiredField(formGroup)).toBe(false);
});
it('should return true if passed in control with the required validator', () => {
expect(hasRequiredField(new FormControl('', Validators.required))).toBe(
true,
);
});
it('should return true if passed in group with nested required validator', () => {
const formGroup = new FormGroup({
hi: new FormGroup({
nested: new FormControl('', Validators.required)
})
});
expect(hasRequiredField(formGroup)).toBe(true);
});
it('should return true if passed in group with required validator', () => {
const formGroup = new FormGroup({
hi: new FormControl('', Validators.required),
});
expect(hasRequiredField(formGroup)).toBe(true);
});
});
import { AbstractControl } from '@angular/forms';
export const hasRequiredField = (abstractControl: AbstractControl): boolean => {
if (!abstractControl) {
return false;
}
if (abstractControl.validator) {
const validator = abstractControl.validator({} as AbstractControl);
if (validator && validator.required) {
return true;
}
}
if (abstractControl['controls']) {
for (const controlName in abstractControl['controls']) {
if (abstractControl['controls'][controlName]) {
if (hasRequiredField(abstractControl['controls'][controlName])) {
return true;
}
}
}
}
return false;
};
<mat-form-field>
<input
matInput
[placeholder]="Enter your username"
type="text"
formControlName="username"
[required]="parentForm.get('username') | hasRequiredField"
>
</mat-form-field>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment