Anoop
Anoop

Reputation: 2798

On click set focus on textarea angular 5

<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

Answers (3)

Vega
Vega

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>
...

DEMO

Upvotes: 11

Madhavan.V
Madhavan.V

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

Zzz
Zzz

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

Related Questions