I would like to avoid white spaces/empty spaces in my angular 2 form? Is it possible? How can this be done?
-
you just have to trim the field as two way data binding. You can consider a custom pipe tooafmeva– afmeva2016-08-30 22:23:15 +00:00Commented Aug 30, 2016 at 22:23
-
Maybe this article can help you blog.angular-university.io/…Bruno João– Bruno João2016-09-02 19:21:15 +00:00Commented Sep 2, 2016 at 19:21
25 Answers
You can create a custom validator to handle this.
new FormControl(field.fieldValue || '', [Validators.required, this.noWhitespaceValidator])
Add noWhitespaceValidator method to your component
public noWhitespaceValidator(control: FormControl) {
return (control.value || '').trim().length? null : { 'whitespace': true };
}
and in the HTML
<div *ngIf="yourForm.hasError('whitespace')">Please enter valid data</div>
9 Comments
I think a simple and clean solution is to use pattern validation.
The following pattern will allow a string that starts with white spaces and will not allow a string containing only white spaces:
/^(\s+\S+\s*)*(?!\s).*$/
It can be set when adding the validators for the corresponding control of the form group:
const form = this.formBuilder.group({
name: ['', [
Validators.required,
Validators.pattern(/^(\s+\S+\s*)*(?!\s).*$/)
]]
});
3 Comments
Validators.pattern(/[\S]/) is cleaner and more readable but will also require at least one character.g to catch all white space. so it would be Validators.pattern(/[\S]/g). Should be: Validators.pattern(/[\S]/g)Maybe this article can help you http://blog.angular-university.io/introduction-to-angular-2-forms-template-driven-vs-model-driven/
In this approach, you have to use FormControl then watch for value changes and then apply your mask to the value. An example should be:
...
form: FormGroup;
...
ngOnInit(){
this.form.valueChanges
.map((value) => {
// Here you can manipulate your value
value.firstName = value.firstName.trim();
return value;
})
.filter((value) => this.form.valid)
.subscribe((value) => {
console.log("Model Driven Form valid value: vm = ",JSON.stringify(value));
});
}
Comments
Prevent user to enter space in textbox in Angular 6
<input type="text" (keydown.space)="$event.preventDefault();" required />
5 Comments
export function noWhitespaceValidator(control: FormControl) {
const isSpace = (control.value || '').match(/\s/g);
return isSpace ? {'whitespace': true} : null;
}
to use
password: ['', [Validators.required, noWhitespaceValidator]]
In template/html
<span *ngIf="newWpForm.get('password').hasError('whitespace')">
password cannot contain whitespace
</span>
2 Comments
If you are using Angular Reactive Forms you can create a file with a function - a validator. This will not allow only spaces to be entered.
import { AbstractControl } from '@angular/forms';
export function removeSpaces(control: AbstractControl) {
if (control && control.value && !control.value.replace(/\s/g, '').length) {
control.setValue('');
}
return null;
}
and then in your component typescript file use the validator like this for example.
this.formGroup = this.fb.group({
name: [null, [Validators.required, removeSpaces]]
});
2 Comments
What I did was created a validator that did the samething as angular for minLength except I added the trim()
import { Injectable } from '@angular/core';
import { AbstractControl, ValidatorFn, Validators } from '@angular/forms';
@Injectable()
export class ValidatorHelper {
///This is the guts of Angulars minLength, added a trim for the validation
static minLength(minLength: number): ValidatorFn {
return (control: AbstractControl): { [key: string]: any } => {
if (ValidatorHelper.isPresent(Validators.required(control))) {
return null;
}
const v: string = control.value ? control.value : '';
return v.trim().length < minLength ?
{ 'minlength': { 'requiredLength': minLength, 'actualLength': v.trim().length } } :
null;
};
}
static isPresent(obj: any): boolean {
return obj !== undefined && obj !== null;
}
}
I then in my app.component.ts overrode the minLength function provided by angular.
import { Component, OnInit } from '@angular/core';
import { ValidatorHelper } from 'app/common/components/validators/validator-helper';
import { Validators } from '@angular/forms';
@Component({
selector: 'app-root',
templateUrl: './app.component.html'
})
export class AppComponent implements OnInit {
constructor() { }
ngOnInit(): void {
Validators.minLength = ValidatorHelper.minLength;
}
}
Now everywhere angular's minLength built in validator is used, it will use the minLength that you have created in the helper.
Validators.compose([
Validators.minLength(2)
]);
Comments
Following directive could be used with Reactive-Forms to trim all form fields so standart Validators.required work fine:
@Directive({
selector: '[formControl], [formControlName]',
})
export class TrimFormFieldsDirective {
@Input() type: string;
constructor(@Optional() private formControlDir: FormControlDirective,
@Optional() private formControlName: FormControlName) {}
@HostListener('blur')
@HostListener('keydown.enter')
trimValue() {
const control = this.formControlDir?.control || this.formControlName?.control;
if (typeof control.value === 'string' && this.type !== 'password') {
control.setValue(control.value.trim());
}
}
}
4 Comments
import { Directive, HostListener, Input, Optional } from '@angular/core'; import { FormControlDirective, FormControlName } from '@angular/forms';control.setValue does not fully update the control resulting in the Chrome autofill save password prompt still including the spaces. Using control.patchValue instead corrects the issue. And for all of you newbies out there, don't forget to import this directive into your global app or shared module.This is a slightly different answer to one below that worked for me:
public static validate(control: FormControl): { whitespace: boolean } {
const valueNoWhiteSpace = control.value.trim();
const isValid = valueNoWhiteSpace === control.value;
return isValid ? null : { whitespace: true };
}
Comments
To avoid the form submition, just use required attr in the input fields.
<input type="text" required>
Or, after submit
When the form is submited, you can use str.trim() to remove white spaces form start and end of an string. I did a submit function to show you:
submitFunction(formData){
if(!formData.foo){
// launch an alert to say the user the field cannot be empty
return false;
}
else
{
formData.foo = formData.foo.trim(); // removes white
// do your logic here
return true;
}
}
3 Comments
To automatically remove all spaces from input field you need to create custom validator.
removeSpaces(c: FormControl) {
if (c && c.value) {
let removedSpaces = c.value.split(' ').join('');
c.value !== removedSpaces && c.setValue(removedSpaces);
}
return null;
}
It works with entered and pasted text.
3 Comments
.trim removes whitespace at the beginning and end of the string whereas split/join removes all spaces (and only spaces, not all whitespace eg, tab, newline) anywhere in the string.I had a requirement where in the Firstname and Lastname are user inputs which were required fields and user should not be able to hit space as the first character.
Import AbstractControl from node_modules.
import { AbstractControl } from '@angular/forms';
check if the first character is space If yes then blank the value and return required: true. If no return null
export function spaceValidator(control: AbstractControl) {
if (control && control.value && !control.value.replace(/\s/g, '').length) {
control.setValue('');
console.log(control.value);
return { required: true }
}
else {
return null;
}
}
the above code will trigger an error if the first character is space and will not allow space to be the first character.
And in form builder group declare
this.paInfoForm = this.formBuilder.group({
paFirstName: ['', [Validators.required, spaceValidator]],
paLastName: ['', [Validators.required, spaceValidator]]
})
Comments
To validate white space in starting in an input you can just call change event and do inline function for that.
<input type="text" class="form-control"
placeholder="First Name without white space in starting"
name="firstName"
#firstName="ngModel"
[(ngModel)]="user.FirstName"
(change) ="user.FirstName = user.FirstName.trim()"
required/>
Comments
If you are using reactive forms in Angular 2+, you can remove leading and trailing spaces with the help of (blur)
app.html
<input(blur)="trimLeadingAndTrailingSpaces(myForm.controls['firstName'])" formControlName="firstName" />
app.ts
public trimLeadingAndTrailingSpaces(formControl: AbstractControl) {
if (formControl && formControl.value && typeof formControl.value === 'string') {
formControl.setValue(formControl.value.trim());
}
}
Comments
In your app.component.html
<form [formGroup]="signupForm">
<input type="text" name="name" [formControl]="signupForm.controls['name']"
placeholder="First Name"
required
/>
<small
*ngIf="signupForm.controls['name'].hasError('pattern')"
class="form-error-msg"
>First Name without space</small>
</form>
In your app.componen.ts file
import { Validators, FormGroup, FormControl } from "@angular/forms";
signupForm: FormGroup;
ngOnInit(){
this.signupForm = new FormGroup({
name: new FormControl("", [
Validators.required,
Validators.pattern("^[a-zA-Z]+$"),
Validators.minLength(3)
])
})
Comments
I am late to the party, but I found most answers not fully functional for my use case. I am using regular expression matching, which detects UTF 8 Whitespace correctly (.trim() does not). Additionally I added a null value check. Code is typescript but should be easy to convert to javascript.
notOnlyWhitespaceValidator(control: AbstractControl) {
const isWhitespace = control.value && control.value.length > 0 && (control.value as string).match(/[^-\s]/) === null;
const isValid = !isWhitespace;
return isValid ? null : { 'only-whitespace': true };
}
Here is a test suite (jest)
describe('notOnlyWhitespaceValidator', () => {
it('should not trigger on missing value', () => {
expect(CustomValidators.notOnlyWhitespaceValidator(new FormControl(''))).toEqual(null);
expect(CustomValidators.notOnlyWhitespaceValidator(new FormControl())).toEqual(null);
});
it('should trigger on only whitespace', () => {
expect(CustomValidators.notOnlyWhitespaceValidator(new FormControl(' '))).toEqual({ 'only-whitespace': true });
expect(CustomValidators.notOnlyWhitespaceValidator(new FormControl('\n'))).toEqual({ 'only-whitespace': true });
// check utf 8 zero with space
const utf8Space = '\ufeff';
expect(CustomValidators.notOnlyWhitespaceValidator(new FormControl(utf8Space))).toEqual({
'only-whitespace': true,
});
});
it('should not trigger on valid input', () => {
expect(CustomValidators.notOnlyWhitespaceValidator(new FormControl(' Whatever is valid '))).toEqual(null);
expect(CustomValidators.notOnlyWhitespaceValidator(new FormControl('!'))).toEqual(null);
});
});
Comments
i have used form valueChanges function to prevent white spaces. every time it will trim all the fields after that required validation will work for blank string.
Like here:-
this.anyForm.valueChanges.subscribe(data => {
for (var key in data) {
if (data[key].trim() == "") {
this.f[key].setValue("", { emitEvent: false });
}
}
}
Edited --
if you work with any number/integer in you form control in that case trim function will not work directly use like :
this.anyForm.valueChanges.subscribe(data => {
for (var key in data) {
if (data[key] && data[key].toString().trim() == "") {
this.f[key].setValue("", { emitEvent: false });
}
}
}
1 Comment
In hello.component.html
<input [formControl]="name" />
<div *ngIf="name.hasError('trimError')" > {{ name.errors.trimError.value }} </div>
In hello.component.ts
import { ValidatorFn, FormControl } from '@angular/forms';
const trimValidator: ValidatorFn = (text: FormControl) => {
if (text.value.startsWith(' ')) {
return {
'trimError': { value: 'text has leading whitespace' }
};
}
if (text.value.endsWith(' ')) {
return {
'trimError': { value: 'text has trailing whitespace' }
};
}
return null;
};`
export class AppComponent {
control = new FormControl('', trimValidator);
}
Comments
export function NoWhitespaceValidator(): ValidatorFn {
return (control: AbstractControl): any => {
window.setTimeout(() => {
if (control.value && control.value != '') {
let trimedvalue = control.value.replace(/\s/g, '');
control.setValue(trimedvalue);
}
}, 10);
};
}
username: ['', Validators.compose([Validators.required, NoWhitespaceValidator()])],
1 Comment
It is better to create custom validator using Angular code and customise it like this:
export function required(control: AbstractControl): ValidationErrors | null {
return isEmptyInputValue(control?.value) ? {'required': true} : null;
}
function isEmptyInputValue(value: any): boolean {
return value == null ||
(typeof value === 'string' && value.trim().length === 0) ||
(Array.isArray(value) && value.length === 0);
}
then you can use your own required validator instead of angular one.
Comments
the following only passes if the string has 0 spaces...
Validators.pattern( /^[\S]*$/ )
Comments
I'm surprised no one proposed this very simple native Reactive Forms pattern which disallows space bar white space (works fine Angular 17+). The first will catch both spacebar white space and a (copy-and-pasted) tab, whereas the second will only catch space bar whitespace:
control.setValidators([Validators.pattern('[^\\s]+')]); // will allow neither spacebar nor tab
control.setValidators([Validators.pattern('[^ ]+')]); // one whitespace inside brackets
For the latter, tab is not considered b/c an accessible form should capture the tab input to move to next focusable element. A copy-and-pasted tab key will not be caught by above regex, but I believe this is an edge case that is not realistic for the OP's purposes.