lHow ca I set focus to a specific field in a formArray?
this is the formArray:
this.productForm = this.formBuilder.array([
this.formBuilder.group({
code: [null],
description: [null],
unitPrice: [null],
qty: [null],
discount: [null],
vat: [null],
total: [null],
amount: [null],
taxAmount: [null]
})
]);
I can have a lot of this formGroup and I need to focus a specific description field. Is there a smart way in angular?
If you know the specific item you want to focus it would be fairly straightforward first of all by adding a template reference:
<input
#fieldName
type="text"
id="fieldName"
name="fieldName"
formControlName="yourFieldName" />
Then in your component (probably in ngAfterViewInit() method):
@ViewChild('fieldName') fieldName: ElementRef;
Then to focus on your element:
this.fieldName.nativeElement.focus();
NB this will be vulnerable to XSS attacks though
Had this same issue. I resolved it by rethinking the implementation.
My situation was that I wanted to focus on the row (first input) when the use tabbed (blurred) out of the last row. I had implemented a directive to handle the blur and focus on my Row.
import { Directive, Input, Output, ElementRef, EventEmitter, HostListener, HostBinding } from '@angular/core';
@Directive({
selector: '[focusedRow]'
})
export class RowDirective {
static tabindex = 1;
static currentFocus = null;
private timer: any = null;
@HostBinding('tabindex') public tabIndex: number = 0;
@Input('formGroupName') public rowNumber: number;
@Output('focus') public onFocus: EventEmitter<number> = new EventEmitter<number>();
@Output('blur') public onBlur: EventEmitter<number> = new EventEmitter<number>();
constructor(private elm: ElementRef) {
this.tabIndex = RowDirective.tabindex++;
}
@HostListener('focusin', ['$event'])
public focusHandler(event: Event) {
// When we're not the current focus.
if (RowDirective.currentFocus !== this) {
this.onFocus.emit(event);
RowDirective.currentFocus = this;
} else {
// Stop our blur from happening since it's the same row
if (this.timer) {
window.clearTimeout(this.timer);
this.timer = null;
}
}
}
@HostListener('focusout', ['$event'])
public blurHandler(event: Event) {
this.timer = window.setTimeout(() => {
// If our row has changed, then we have blurred.
this.onBlur.emit(event);
// Clear if this is still listed as the Focused Row.
if (RowDirective.currentFocus === this) {
RowDirective.currentFocus = null;
}
}, 200);
}
}
What I did was, instead of trying to battle the Angular Form Group, I simply made it that when a new Row was created from my Reactive Form and the row was added, because the form row element had the directive applied, the better solution was to simply focus the row (first input) when the directive initialised.
This was done using the OnInit
interface. So the above code was adjusted to include the interface (changes below);
import { Directive, Input, Output, OnInit, ElementRef, EventEmitter, HostListener, HostBinding } from '@angular/core';
@Directive({
selector: '[focusedRow]'
})
export class RowDirective implements OnInit {
....
ngOnInit() {
// Focus on the first Form Element
this.elm.nativeElement.querySelector('input').focus();
}
....
}
So create the above Directive, and then add that directive to your Form Array element...
<tr *ngFor="let entry of myForms.controls; let index=index" [formGroupName]="index" focusedRow (focus)="rowFocus(index)" (blur)="rowBlur(index)">
This way, anytime a row is created, it focuses the first form element.
The beauty of this solution is that it also works when the user clicked my "Add new Row" button, and you get some cool Focus and Blur handlers on your [table] row. (the secret to that by the way is the use of the tabindex
attribute)
Hope that helps your situation.
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