Reputation: 24943
In Angular2 how to know when ANY input field has lost focus..! If I use observables on the form:
form.valueChange.subscribe...
wont work since I really want to know when a field lost it's blur (focus) so I can update my store (if I update the store before losing focus, my cursor on a text input gets moved to the end, since the data gets swapped which is weird looking)
of course I can also add (change)=""
on each input, but I have a lot of'em...
I was thinking something of the sorts of:
this.form.valueChanges.debounceTime(1000).subscribe((changes:any) => {
if (this.form.dirty){
this.appStore.dispatch(this.resellerAction.updateResellerInfo(changes))
}
});
but the problem is that the dirty remains dirty, so it stuck in an everlasting loop of change detections...
tx
Sean
Upvotes: 17
Views: 19880
Reputation: 301
This solution is working for Angular 18:
use (focusout)="focusOut($event)"
The beautiful thing is, you can use the (focusout) on a field level, but also on higher levels like on the form to capture the focusout of all its fields.
Example:
in the .HTML file:
<input matInput type="text" formControlName="avatar_name (focusout)="focusOut($event)">
in the .ts file:
focusOut(event: any): void {
// your logic
}
Upvotes: 0
Reputation: 378
Why not use focusout it bubbles by default in the DOM
Here's a simple directive that catches focusout and checks if input value is blank, then sets value to zero:
@Directive({
selector: '[blankToZero]'
})
export class BlankToZeroDirective {
constructor(private elementHost: ElementRef) { }
@HostListener('focusout')
ensureInput(): void {
if (Util.isNullOrEmpty(this.elementHost.nativeElement.value)) {
this.elementHost.nativeElement.value = 0;
}
}
}
Upvotes: 13
Reputation: 657108
The blur
event doesn't bubble, therefore we need to listen on every input element directly. Angular provides a nice solution for this situation.
A directive that applies to all input elements inside your template.
This directive uses a host-listener to listen for the blur
events on all elements where the selector applies and forwards a bubbling input-blur
event:
@Directive({
selector: 'input,select',
host: {'(blur)': 'onBlur($event)'}
})
class BlurForwarder {
constructor(private elRef:ElementRef, private renderer:Renderer) {}
onBlur($event) {
this.renderer.invokeElementMethod(this.elRef.nativeElement,
'dispatchEvent',
[new CustomEvent('input-blur', { bubbles: true })]);
// or just
// el.dispatchEvent(new CustomEvent('input-blur', { bubbles: true }));
// if you don't care about webworker compatibility
}
}
By adding the BlurForwarder
directive to directives: [...]
it will be applied to all elements in its template that match the selector.
The host-listener listens for bubbling input-blur
events and calls our event handler:
@Component({
selector: 'my-component',
directives: [BlurForwarder],
host: {'(input-blur)':'onInputBlur($event)'},
template: `
<form>
<input type="text" [(ngModel)]="xxx">
<input type="text" [(ngModel)]="yyy">
<input type="text" [(ngModel)]="zzz">
</form>`
}) {
onInputBlur(event) {
doSomething();
}
}
Upvotes: 28