In my app I want to automatically set focus on first field of form on component load. Can anyone please guide how to achieve this without any repetition as I want this on every form (Reactive Forms) in my app.
You should use an directive to achieve this behavior.
This will show you the way how to do it: https://plnkr.co/edit/ttxCP7vCLkLtNb3Xiaah?p=preview
import {Component, NgModule, Directive, ElementRef, Renderer} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'
@Directive({
selector: 'form[anyNameHere]'
})
export class SelectFirstInputDirective {
constructor(private _eRef: ElementRef, private _renderer : Renderer) { }
private _getInputElement(nativeElement: any): any {
if (!nativeElement || !nativeElement.children) return undefined;
if (!nativeElement.children.length && nativeElement.localName === 'input' && !nativeElement.hidden) return nativeElement;
let input;
[].slice.call(nativeElement.children).every(c => {
input = this._getInputElement(c);
if (input) return false; // break
return true; // continue!
});
return input;
}
ngAfterViewInit() {
let formChildren = [].slice.call(this._eRef.nativeElement.children);
formChildren.every(child => {
let input = this._getInputElement(child);
if (input) {
this._renderer.invokeElementMethod(input, 'focus', []);
return false; // break!
}
return true; // continue!
});
}
}
@Component({
selector: 'my-app',
template: `
<div>
<h2>Hello {{name}}</h2>
<form anyNameHere>
<div class="form-group">
<input hidden formcontrolname="firstName" type="text" class="form-control input-sm ng-pristine ng-valid ng-touched" placeholder="First Name" id="firstName">
<label class="col-sm-3 control-label" for="firstName">Name</label>
<div class="col-sm-9 form-inline">
<div class="form-group">
<div class="col-sm-12">
<input formcontrolname="firstName" type="text" class="form-control input-sm ng-pristine ng-valid ng-touched" placeholder="First Name" id="firstName">
</div>
</div>
<div class="form-group">
<div class="col-sm-12">
<input formcontrolname="lastName" type="text" class="form-control input-sm ng-untouched ng-pristine ng-valid" placeholder="Last Name" id="lastName">
</div>
</div>
</div>
</div>
</form>
</div>
`,
})
export class App {
constructor() {
this.name = 'Angular2'
}
}
@NgModule({
imports: [ BrowserModule ],
declarations: [ App, SelectFirstInputDirective ],
bootstrap: [ App ]
})
export class AppModule {}
Render
here !! It should be the last resort to MANIPULATE with ElementRef, not to check those childs and so on.. –
Null type="hidden"
instead of the attribute hidden
!! See this plunker: plnkr.co/edit/azdVcdRSgER13qAcM97a?p=preview I just pointed you to the idea, everything else is now your job! ;) –
Null .localName === 'input'
to 'textarea'
–
Null you can achieve this by simply adding the "autofocus" attribute to your input element like.
<input class="form-control" [formControl]="name" autofocus>
You should use an directive to achieve this behavior.
This will show you the way how to do it: https://plnkr.co/edit/ttxCP7vCLkLtNb3Xiaah?p=preview
import {Component, NgModule, Directive, ElementRef, Renderer} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'
@Directive({
selector: 'form[anyNameHere]'
})
export class SelectFirstInputDirective {
constructor(private _eRef: ElementRef, private _renderer : Renderer) { }
private _getInputElement(nativeElement: any): any {
if (!nativeElement || !nativeElement.children) return undefined;
if (!nativeElement.children.length && nativeElement.localName === 'input' && !nativeElement.hidden) return nativeElement;
let input;
[].slice.call(nativeElement.children).every(c => {
input = this._getInputElement(c);
if (input) return false; // break
return true; // continue!
});
return input;
}
ngAfterViewInit() {
let formChildren = [].slice.call(this._eRef.nativeElement.children);
formChildren.every(child => {
let input = this._getInputElement(child);
if (input) {
this._renderer.invokeElementMethod(input, 'focus', []);
return false; // break!
}
return true; // continue!
});
}
}
@Component({
selector: 'my-app',
template: `
<div>
<h2>Hello {{name}}</h2>
<form anyNameHere>
<div class="form-group">
<input hidden formcontrolname="firstName" type="text" class="form-control input-sm ng-pristine ng-valid ng-touched" placeholder="First Name" id="firstName">
<label class="col-sm-3 control-label" for="firstName">Name</label>
<div class="col-sm-9 form-inline">
<div class="form-group">
<div class="col-sm-12">
<input formcontrolname="firstName" type="text" class="form-control input-sm ng-pristine ng-valid ng-touched" placeholder="First Name" id="firstName">
</div>
</div>
<div class="form-group">
<div class="col-sm-12">
<input formcontrolname="lastName" type="text" class="form-control input-sm ng-untouched ng-pristine ng-valid" placeholder="Last Name" id="lastName">
</div>
</div>
</div>
</div>
</form>
</div>
`,
})
export class App {
constructor() {
this.name = 'Angular2'
}
}
@NgModule({
imports: [ BrowserModule ],
declarations: [ App, SelectFirstInputDirective ],
bootstrap: [ App ]
})
export class AppModule {}
Render
here !! It should be the last resort to MANIPULATE with ElementRef, not to check those childs and so on.. –
Null type="hidden"
instead of the attribute hidden
!! See this plunker: plnkr.co/edit/azdVcdRSgER13qAcM97a?p=preview I just pointed you to the idea, everything else is now your job! ;) –
Null .localName === 'input'
to 'textarea'
–
Null HTML autofocus attribute do exactly that
<input type="text" name="fname" autofocus>
import { AfterViewInit, Directive, ElementRef } from '@angular/core';
@Directive({
selector: 'form[appFocusFirstInput]'
})
export class FocusFirstInputDirective implements AfterViewInit {
constructor(
private element: ElementRef
) {
}
ngAfterViewInit(): void {
const input = this.element.nativeElement.querySelector('input');
if (input) {
input.focus();
}
}
}
With Angular 4,Renderer has been deprecated, so the directive way is gone. But anyhow you can always use a "quick and dirty" way: add the reference to the element you want to set focus on and just use <reference-name>.focus()
<form [formGroup]="form" (ngSubmit)="onSubmit(form, $event); needFocus.focus()">
<input placeholder="" formControlName="name" #needFocus>
</form>
Following approaches you can use => 1. You can do this by autoFoucs directive OR 2. Provide reference to your control like
<input hidden #firstName formcontrolname="firstName" type="text" class="form-control input-sm ng-pristine ng-valid ng-touched" placeholder="First Name" id="firstName">
Then in ts file declare like this
export class App implements OnInit{
@ViewChild('firstName') firstNameTextbox;
constructor() {
}
ngOnInit() {
this.firstNameTextbox.nativeElement.focus();
}
}
© 2022 - 2024 — McMap. All rights reserved.