components
components copied to clipboard
feat(input): add (limited) support for text masking
Bug, feature request, or proposal:
How can I set a text mask in date picker component so, if user doesn't want to select a date in calendar, he can type and fill correctly the field?
What is the expected behavior?
When click on input date picker, show the mask so user can type date instead of selecting a date from calendar
What is the current behavior?
empty input
What are the steps to reproduce?
Providing a StackBlitz/Plunker (or similar) is the best way to get the team to see your issue.
Plunker starter (using on @master
): https://goo.gl/DlHd6U
StackBlitz starter (using latest npm
release): https://goo.gl/wwnhMV
Just add a datepicker component
What is the use-case or motivation for changing an existing behavior?
Maybe user wants to type date instead of selecting form calendar.
Which versions of Angular, Material, OS, TypeScript, browsers are affected?
@angular/cli: 1.3.0 node: 6.10.3 os: darwin x64 @angular/animations: 4.3.5 @angular/cdk: 2.0.0-beta.8 @angular/common: 4.3.5 @angular/compiler: 4.3.5 @angular/core: 4.3.5 @angular/flex-layout: 2.0.0-beta.8 @angular/forms: 4.3.5 @angular/http: 4.3.5 @angular/material: 2.0.0-beta.8 @angular/platform-browser: 4.3.5 @angular/platform-browser-dynamic: 4.3.5 @angular/router: 4.3.5 @angular/cli: 1.3.0 @angular/compiler-cli: 4.3.5 @angular/language-service: 4.3.5
Is there anything else we should know?
a) material doesn't provide mask behavior b) it's currently impossible to open datepicker with focus, while keeping focus on the input (because of how Overlay works)
Hey @fxck ! Thanks for the answer! Well... there's no need to keep focus on text input wile calendar is open! If user click on input, just show the mask. If user clicks on button, hide mask and show calendar! Is that possible?
Yes, but as I said, material doesn't provide that functionality, you can use something like https://github.com/text-mask/text-mask
https://github.com/text-mask/text-mask dont work with ngmodel
As mentioned above, text-mask won't work with material2. This is because angular doesn't allow input fields to have more than 1 ValueAcessor.
A work around is to use the vanilla version of text-mask:
1 - Import the library in your component
import * as textMask from "vanilla-text-mask/dist/vanillaTextMask.js";
2 - Add your mask in the component and init your input (don't forget to import AfterViewInit and implement it to your component)
mask = [ /[1-9]/, /\d/, /\d/];
maskedInputController;
@ViewChild("input", { read: ViewContainerRef }) public input;
ngAfterViewInit(): void {
setTimeout(() => {
this.maskedInputController = textMask.maskInput({
inputElement: this.input.element.nativeElement,
mask: this.mask
});
});
}
ngOnDestroy() {
this.maskedInputController.destroy();
}
3 - in your template, make sure the input element has an #input attribute
<mat-form-field class="input">
<input matInput [matDatepicker]="picker" [(ngModel)]="selectedValue" #input>
<mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
<mat-datepicker #picker></mat-datepicker>
</mat-form-field>
I @remborg ! I was trying to set a mask like 'dd/mm/yyyy' and validate things like day 32 or month 13. I can't figure out how to do that using vanilla-text-mask, do you know if is possible?
Thanks!
Hi @WandersonAlves I can see 2 ways to do that, the first one would be to use the date pipe in the text-mask-addons lib, but you'll likely have to create a custom pipe for some mask formats. The second way would be to do it on the angular side, catching when the input value changes and then doing a check. Not really clean I think because then the input validation is half vanilla, half angular... but as a workaround that would work. Good luck and please let me know what you go for :)
+1 would like a way to add masking that inserts slashes
Upping the priority of this as we'll need to add at least limited masking support to allow for prefix and suffix text now that we're only recommending matPrefix
and matSuffix
for icons (or other centered content) .
See related discussion on #9488
We were able to get a mask directive working with Material inputs using the text-mask
library mentioned above. You can see the code here if it's helpful (at least until an official solution is offered).
Just a heads up that we kicked off a community voting process for your feature request. There are 20 days until the voting process ends.
Find more details about Angular's feature request process in our documentation.
Thank you for submitting your feature request! Looks like during the polling process it didn't collect a sufficient number of votes to move to the next stage.
We want to keep Angular rich and ergonomic and at the same time be mindful about its scope and learning journey. If you think your request could live outside Angular's scope, we'd encourage you to collaborate with the community on publishing it as an open source package.
You can find more details about the feature request process in our documentation.
Any way of using mask in mat-input without using a third party library? It would be nice to use a currency mask based on the currency pipe and the LocaleID of the app.
is there an official solution without using third party library today ?
Input masking is a really basic functionality to have in a UI library. Is there any news on this issue? Is this planned or what?