Reputation: 10320
I am working on a small project written in Angular 8 and Angular Material.
I have a number field where I want to specify min and max values, however I couldn't find any documentation on how to do that in the matInput documentation.
Question: Does matInput
support min/max validations? What is the best way of validation number fields in Angular Material?
So far I tried the standard html5 min and max properties which unfortunately are not caught by the validation engine. I also tried some examples from the internet which turned to be not working in Angular 8.
Upvotes: 3
Views: 15783
Reputation: 89
editForm: FormGroup = this.fb.group({
quantity: []
});
changeMaxValue(val: number): void {
this.maxValue = val;
this.editForm.get('quantity')?.setValidators(Validators.max(val));
}
and in html,You can set custom mat-error.
<mat-form-field appearance="outline">
<mat-label>Quantity</mat-label>
<input matInput formControlName="quantity" type="text">
<mat-error *ngIf="editForm.get('quantity')!.invalid">
<span *ngIf="editForm.get(['quantity'])!.hasError('max')">{{'entity.validation.max' | translate: { max: maxValue } }}</span>
</mat-error>
</mat-form-field>
and in translate json file,You can set as below
{
"entity": {
"validation": {
"max": "This field cannot be more than {{ max }}."
}
}
}
Upvotes: 0
Reputation: 8828
Angular template-driven forms are not able to Validate the min and max HTML5 validation by default - It's a framework issue. Either you write a directive to solve this issue or else a simpler solution is to validate the form on submit.
the problem I am stating can be seen and tested here https://stackblitz.com/edit/angular-input-min-max?file=src/app/app.component.html
A few directives are available, one I was able to find but its has some issues as well. Try yourself
https://www.concretepage.com/angular-2/angular-4-min-max-validation#Template-driven
the other possible and clean approach is to use a Reactive form and not template-driven forms in your code :)
Upvotes: 1
Reputation: 5181
You can use the reactive approach for creating forms. These might seem to be scary in the first time, but in the end it will be super helpful in setting up different validators.
Step 1: Import dependencies
import { ReactiveFormsModule } from '@angular/forms';
@NgModule({
imports: [
// other imports ...
ReactiveFormsModule
],
})
export class AppModule { }
Step 2: Create a new FormObject
import { Component } from '@angular/core';
import { FormGroup, FormControl } from '@angular/forms';
@Component({
selector: 'app-profile-editor',
templateUrl: './profile-editor.component.html',
styleUrls: ['./profile-editor.component.css']
})
export class ProfileEditorComponent {
profileForm = new FormGroup({
firstName: new FormControl(''),
lastName: new FormControl(''),
});
}
Step 3: Create the template
<form [formGroup]="profileForm">
<label>
First Name:
<input type="text" formControlName="firstName">
</label>
<label>
Last Name:
<input type="text" formControlName="lastName">
</label>
</form>
Step 4: Add validators
import { Component } from '@angular/core';
import { FormGroup, FormControl } from '@angular/forms';
@Component({
selector: 'app-profile-editor',
templateUrl: './profile-editor.component.html',
styleUrls: ['./profile-editor.component.css']
})
export class ProfileEditorComponent {
profileForm = new FormGroup({
firstName: ['', Validators.required, Validators.min(3)],
lastName: ['', Validators.required, Validators.min(3)]
});
}
Upvotes: 3
Reputation: 796
I recommend you use Reactive Forms as it will make your business logic stay in the ts code, keeping your templates easier to read and maintain.
sampleForm = new FormGroup({}) // Instantiating our form
constructor(private fb: FormBuilder){ // Injecting the ReactiveForms FormBuilder.
this.sampleForm = fb.group({
// Adding the "age" input to our FormGroup along with its min-max Validators.
'age': ['', [Validators.min(5), Validators.max(10)]]
})
}
And your html
<form [formGroup]="sampleForm ">
<label for="age">Age</label>
<!-- formControlName will bind the age field declared in the ts code. -->
<input type='number' id="age" formControlName="age">
</form>
Upvotes: 3
Reputation: 1485
In order to validate the content of a matInput you can wrap it in a mat-form-field like so:
<form class="example-form">
<mat-form-field class="example-full-width">
<input matInput [formControl]="numberFormControl">
<mat-error *ngIf="numberFormControl.hasError('min')">
The value is lower than the minimum
</mat-error>
<mat-error *ngIf="numberFormControl.hasError('max')">
The value is greater than the maximum
</mat-error>
</mat-form-field>
</form>
And use form control for the validators:
import {Component} from '@angular/core';
import {FormControl, Validators} from '@angular/forms';
@Component({
selector: 'input-errors-example',
templateUrl: 'input-errors-example.html',
styleUrls: ['input-errors-example.css'],
})
export class InputErrorsExample {
numberFormControl = new FormControl('', [
Validators.min(3),
Validators.max(6),
]);
}
This works for minimum and maximum values, you can use the minlength and maxlength validators in the same fashion, the documentation is here:
https://angular.io/api/forms/Validators
Upvotes: 4
Reputation: 10717
Try:
minlength
and maxlength
But the type should not be a number, Like:
<input matInput placeholder="Test" minlength="3" maxlength="3">
Upvotes: -2