I am using the directive to validate the mobile number input
import { Directive, ElementRef, HostListener, Input } from '@angular/core';
@Directive({
selector: '[mobileNumber]'
})
export class MobileNumberDirective {
@Input()
public value: any;
constructor(private el: ElementRef) { }
@HostListener('keypress', ['$event'])
onKeyDown(event: KeyboardEvent) {
var inp = String.fromCharCode(event.keyCode);
if (/[0-9]/.test(inp)) {
return true;
} else {
if (event.keyCode == 8 || (event.keyCode == 43 && this.value == '')) {
return true;
} else {
event.preventDefault();
return false;
}
}
}
}
The input field is this :
<input
type="text"
placeholder="Search Mobile"
autocomplete="off"
[value]="'1111199999'"
mobileNumber
/>
here, the [value] is not working when the directive is applied but working fine without it.
CodePudding user response:
You are using bi-directional in Ui, So once you assign the direct value (number or string) will not work.
<input
type="text"
placeholder="Search Mobile"
autocomplete="off"
[value]="value" <-- bind your property
mobileNumber
/>
Please refer the Link
I hope this solution is clear to you
CodePudding user response:
You are not indicate to your directive that the element show the "value" (you can see more clear if you choose as name of your input, e.g. "myValue")
You can implements OnInit and write
ngOnInit{
this.el.nativeElement.value=this.value;
}
BTW, you're using a directive not for validate, else to avoid keydown a "not number".
We can use the ngOnInit also to check at first if value fullfilled the condition.
ngOnInit{
if (this.value)
this.el.nativeElement.value=this.value.replace(/[^0-9]/g,'')
}
Well, you can also use [(ngModel)]
to have a two-binding to get the value of the variable (also you can use [attr.value]
instead of [value] and remove the @Input() value
from your directive
To use either, [(ngModel)] or [value] you directive can be like
@Input()
public value: any;
//see in constructor how inject a "NgControl"
constructor(private el: ElementRef,@Optional() private control:NgControl) {}
@HostListener('keypress', ['$event'])
onKeyDown(event: KeyboardEvent) {
...
}
ngOnInit(){
setTimeout(()=>{
if (this.control)
this.control.control.setValue(
this.control.value?this.control.value.replace(/[^0-9]/g,''):
'')
else
this.el.nativeElement.value=this.value?this.value.replace(/[^0-9]/g,''):
''
})
}
CodePudding user response:
Please use RegexFormate Validation and after set [maxlength]="10" like this this is good option to add validation
Example :
<div >
<mat-form-field appearance="outline">
<mat-label>Mobile No (First)</mat-label>
<input matInput [formControl]="mobile1" [maxlength]="10" appRegexFormate regexType="number"
autoComplete='off' [(ngModel)]="merchantModelAdd.mobile1" required>
<mat-error *ngIf="mobile1.hasError('required')">Mobile No (First) cannot be
empty
</mat-error>
<mat-error *ngIf="mobile1.hasError('pattern')">Invalid mobile No (First)
</mat-error>
</mat-form-field>
</div>
Regex Class
import {Directive, ElementRef, HostListener, Input} from '@angular/core';
@Directive({
selector: '[appRegexFormate]'
})
export class RegexFormateDirective {
@Input('regexType') numericType: string;
private regex = {
number: new RegExp(/^\d $/),
letter_only: new RegExp(/^[a-zA-Z] $/g),
letter_space: new RegExp(/^[a-zA-Z ] $/g),
letter_num: new RegExp(/^[a-zA-Z0-9] $/g),
letter_num_space: new RegExp(/^[a-zA-Z0-9 ] $/g),
letter_num_special: new RegExp(/^[a-zA-Z0-9-@#$%^&*!()_ \-=\[\]{};':"\\|,.<>\/?] $/g),
remark: new RegExp(/^[a-zA-Z0-9-@#$%^&*!()_ \-=\[\]{};:\\,.<>\/? \n] $/g),
url: new RegExp(/^[a-zA-Z\-] $/g),
decimal: new RegExp(/^[0-9] (\.[0-9]*){0,1}$/g),
email: new RegExp(/^[a-zA-Z0-9@_.] $/g),
long_lat_number: new RegExp(/^[0-9]{0,3}(\.[0-9]{0,5})?$/g)
};
private specialKeys = {
number: ['Backspace', 'Tab', 'End', 'Home', 'ArrowLeft', 'ArrowRight'],
letter_only: [ 'Backspace', 'Tab', 'End', 'Home', 'ArrowLeft', 'ArrowRight' ],
letter_space: [ 'Backspace', 'Tab', 'End', 'Home', 'ArrowLeft', 'ArrowRight' ],
letter_num: [ 'Backspace', 'Tab', 'End', 'Home', 'ArrowLeft', 'ArrowRight' ],
letter_num_space: [ 'Backspace', 'Tab', 'End', 'Home', 'ArrowLeft', 'ArrowRight' ],
letter_num_special: [ 'Backspace', 'Tab', 'End', 'Home', 'ArrowLeft', 'ArrowRight' ],
remark: [ 'Backspace', 'Tab', 'End', 'Home', 'ArrowLeft', 'ArrowRight'],
url: [ 'Backspace', 'Tab', 'End', 'Home', 'ArrowLeft', 'ArrowRight' ],
decimal: [ 'Backspace', 'Tab', 'End', 'Home', 'ArrowLeft', 'ArrowRight' ],
email: [ 'Backspace', 'Tab', 'End', 'Home', 'ArrowLeft', 'ArrowRight' ],
long_lat_number: [ 'Backspace', 'Tab', 'End', 'Home', 'ArrowLeft', 'ArrowRight' ],
};
constructor(private elementRef: ElementRef) {
}
@HostListener('keydown', ['$event'])
onKeyDown(event: KeyboardEvent) {
if (this.specialKeys[this.numericType].indexOf(event.key) !== -1) {
return;
}
const current: string = this.elementRef.nativeElement.value;
const next: string = current.concat(event.key);
if (next && !String(next).match(this.regex[this.numericType])) {
event.preventDefault();
}
}
@HostListener('click', ['$event'])
onKeyDown2(event: KeyboardEvent) {
const current: string = this.elementRef.nativeElement.value;
const element = this.elementRef.nativeElement;
if (current) {
if (!String(current).match(this.regex[this.numericType])) {
this.elementRef.nativeElement.value = '';
setTimeout(function (evet) {
element.click();
}, 100);
}
}
}
@HostListener('paste', ['$event']) blockPaste(e: KeyboardEvent) {
e.preventDefault();
}
}
use like this this is best option