Reputation: 2798
<div class="posts">
<div class="post">
<div>post content</div>
<a class="comment">Comment</a>
<textarea [(ngModel)]= "model.text" class="comment-text" name="text"></textarea>
</div>
<div class="post">
<div>post content</div>
<a class="comment">Comment</a>
<textarea [(ngModel)]= "model.text" class="comment-text" name="text"></textarea>
</div>
</div>
...
I want to set focus on textarea on 'a' click. Can anyone please help me. I'm using angular 5
Upvotes: 5
Views: 21977
Reputation: 28738
You can set focus directly from your markup in HTML file if you use template variables. You can reference it in (click)
method. This way, no need to access DOM thru the code, it stays in HTML file, easier for debugging:
HTML
...
<textarea #textarea1 [(ngModel)]="text" class="comment-text" name="text"></textarea>
<button (click)="textarea1.focus()">SetFocus on the first textarea</button>
...
<textarea #textarea2 [(ngModel)]="text" class="comment-text" name="text"></textarea>
<button (click)="textarea2.focus()">SetFocus on the second textarea</button>
...
Upvotes: 11
Reputation: 845
Here you may go for loop the <div class="post">
,
<div class="posts">
<div class="post">
<div>post content</div>
// Pass index here, if you want to achieve dynamically
<a class="comment" (click)="doSomething(0)">Comment</a>
<textarea [(ngModel)]= "model.text" class="comment-text" #txtArea name="text">
</textarea>
</div>
<div class="post">
<div>post content</div>
<a class="comment" (click)="doSomething(1)">Comment</a>
<textarea [(ngModel)]= "model.text" class="comment-text" #txtArea name="text">
</textarea>
</div>
</div>
Now in your ts file add the following imports,
import { Component, ViewChildren, QueryList, ElementRef } from '@angular/core';
Read elements using ViewChildren
and QueryList
like this,
@ViewChildren("txtArea") textAreas:QueryList<ElementRef>;
Finally your doSomething
event handler like this,
doSomething(index: number) {
this.textAreas.find((item, idx) => {
return idx === index;
}).nativeElement.focus();
}
Update
The above code will work with an array of posts
. So we don't need to hard-code the id like #txtArea1, #txtArea2 etc.
Please check here the DEMO_1
If you are iterating <div class="post">
like,<div class="post" *ngFor="let post of posts; index as i">
You can pass the index
(here i
) to get corresponding TextArea
reference from QueryList
like below,
<a class="comment" (click)="textAreas.toArray()[i].nativeElement.focus()">Comment</a>
Check the complete code here DEMO_2
Upvotes: 5
Reputation: 3035
You can use the @ViewChild decorator. Documentation: https://angular.io/api/core/ViewChild.
You need to assign a name to your input element and wire up a click event.
<textarea #inputToFocus />
<a (click)="focusInput()">Click</button>
In your component, use @ViewChild to search for the element, then implement the click handler to perform whatyou need.
export class App implements AfterViewInit {
@ViewChild("inputToFocus") inputElement: ElementRef;
focusInput() {
this.inputElement.nativeElement.focus()
}
NOTE:The inputElement
variable will be first available, when ngAfterViewInit
event fires.
UPDATE DUE TO UPDATED QUESTION: To handle multiple elements you would need to use @ViewChildren Documentation: https://angular.io/api/core/ViewChildren
In the code example you gave above I would make the redundant code into its own component to encapsulate the repeated functionality.
Upvotes: 4