I've created a directive to limit the length of input
field type=number
.
// Input
<input min="1" appLimitTo [limit]="5" type="number" name="property" [(ngModel)]="property">
// Directive
import {Directive, HostListener, Input} from '@angular/core';
@Directive({
selector: '[appLimitTo]',
})
export class LimitToDirective {
@Input() limit: number;
@Input() ngModel: any;
@HostListener('input', ['$event'])
onInput(e) {
if (e.target.value.length >= +this.limit) {
e.target.value = (e.target.value).toString().slice(0, this.limit - 1);
e.preventDefault();
}
}
}
It works fine if we enter the value through the keyboard. But the problem arises when if I copy & paste 12345678913465789
this number, this line e.target.value = (e.target.value).toString().slice(0, this.limit - 1);
shorten it to the limit, but the ngModel
still contains 12345678913465789
value. How to update this ngModel value?
Please help.
PS - What should I add in my directive to meet the requirement?
If we use two way binding syntax for ngModel the value will be updated. So the default (ngModelChange) function will update the value of ngModel property. i.e., user.Name . And the second (ngModelChange) will be triggered printing the user name value in the console.
The ngModel directive binds an input , select , textarea (or custom form control) to a property on the scope using NgModelController, which is created and exposed by this directive. ngModel is responsible for: Binding the view into the model, which other directives such as input , textarea or select require.
The answer is: (ngModel) causes a 1-way data-binding, whereas [(ngModel)] ensures a two-way data binding.
You can inject NgControl
into your own directive. You can then listen to the control valueChanges
event.
limit-to.directive.ts
import {Directive, HostListener, Input, OnInit, OnDestroy} from '@angular/core';
import {NgControl} from '@angular/forms';
import {map} from 'rxjs/operators';
import {Subscription} from 'rxjs/Subscription';
@Directive({
selector: '[appLimitTo]',
})
export class LimitToDirective implements OnInit, OnDestroy {
@Input('appLimitTo') limit: number;
private subscription: Subscription;
constructor(private ngControl: NgControl) {}
ngOnInit() {
const ctrl = this.ngControl.control;
this.subscription = ctrl.valueChanges
.pipe(map(v => (v || '').toString().slice(0, this.limit)))
.subscribe(v => ctrl.setValue(v, { emitEvent: false }));
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
}
usage:
<input ngModel appLimitTo="3" type="number" />
Live demo
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With