maxbellec
maxbellec

Reputation: 17451

Focus on input right after its creation

I would like to have my input focused when it is 'activated'. The reason for that is that I am building a multi step form (like this one), which has multiple inputs that I am showing one by one. This is what I tried.

Solution 1

@Component(
...
template: `<input *ngIf="myCondition" id="myId" (load)="myLoad()">`){
    myCondition = false;
    load(){
        document.getElementById("myId").focus();
    }
}

The (load) event is not triggered when when myCondition later becomes true, it would seem to me to be the most logical DOM event in that case.

Solution 2

someFunction(){
    this.myCondition = true;
    document.getElementById("myId").focus();
}

This fails becomes the input element has not yet been loaded: document.getElementById("myId") returns undefined. It does work if I setTimeOut it one something like 100ms, but it is not a very elegant solution and the ideal timeout would be different on different clients.

Any other idea on how to achieve input focus when input is loaded in the DOM?

Upvotes: 3

Views: 3633

Answers (2)

akn
akn

Reputation: 3722

For dynamically created inputs, i.e in a table, it can be done using @ViewChildren changes listener

Template:

<tr *ngFor="let row of rows">    
  <td>
    <input type="text" #name>
  </td>
</tr>

Component

@Component({
  selector: 'my-component',
  templateUrl: './my-componentt.html',
  styleUrls: ['./my-component.scss']
})
export class MyComponent implements OnInit, AfterViewInit {

  @ViewChildren('name') nameInputs: QueryList<ElementRef>

  ngAfterViewInit(): void {
    this.nameInputs.changes.subscribe(()=>{
      setTimeout(()=>{
        this.nameInputs.last.nativeElement.focus()
      });
    })
  }

}

Upvotes: 1

micronyks
micronyks

Reputation: 55443

Finally found the solution for your problem. I have made one directive called focus which takes care of current input.

Working DEMO : http://plnkr.co/edit/TzQNL6DcIJ9tjAntu6Si?p=preview

@Directive({      
  selector:'[focus]',
})

export class focusDirective{

  constructor(private el:ElementRef, private rd:Renderer){        
      console.log(this.el.nativeElement);
      rd.setElementStyle(el.nativeElement,'background','yellow');
  }

  ngAfterViewInit(){
      this.el.nativeElement.focus();
  }
}

Component.ts

@Component({
  selector: 'my-app',
  directives:[focusDirective],
  template: `
    <div  *ngIf="step==1"> 
        #{{step}}step :<input focus type="text">  
      </div>
      <div *ngIf="step==2">
        #{{step}}step : <input focus type="text">
      </div>
      <div *ngIf="step==3">
        #{{step}}step : <input focus type="text">
    </div>
      <hr>
      <button (click)="next()">NEXT</button>
  `
})
export class App {
  step=1;
  next(){
    ++this.step;
  }
}

Upvotes: 5

Related Questions