2017-01-26 5 views
23

Как я могу использовать элемент ввода автофокуса? Как this вопрос, но не с AngularDart. Что-то вроде этого:Angular2 + элемент ввода автофокуса

<input type="text" [(ngModel)]="title" [focus] /> 
//or 
<input type="text" [(ngModel)]="title" autofocus /> 

У Angular2 есть встроенная поддержка этой функции?

Самый лучший вопрос: this one, но есть ли более короткие/простые решения, так как у меня нет «списка полей ввода». В представленной ссылке используется *ngFor="#input of inputs", но у меня только 1 вход в шаблоне управления.

+0

Вторая альтернатива должна работать прямо из коробки. Это не так? – Hampus

+0

Нет, это не так. – Makla

+2

Просто использование «автофокусировки» не работает, потому что это действует только при загрузке страницы, а не в том случае, когда Angular меняет содержимое. – Dave

ответ

38

Это мой текущий код:

import { Directive, ElementRef, Input } from "@angular/core"; 

@Directive({ 
    selector: "[autofocus]" 
}) 
export class AutofocusDirective 
{ 
    private focus = true; 

    constructor(private el: ElementRef) 
    { 
    } 

    ngOnInit() 
    { 
     if (this.focus) 
     { 
      //Otherwise Angular throws error: Expression has changed after it was checked. 
      window.setTimeout(() => 
      { 
       this.el.nativeElement.focus(); //For SSR (server side rendering) this is not safe. Use: https://github.com/angular/angular/issues/15008#issuecomment-285141070) 
      }); 
     } 
    } 

    @Input() set autofocus(condition: boolean) 
    { 
     this.focus = condition !== false; 
    } 
} 

Прецедент:

[autofocus] //will focus 
[autofocus]="true" //will focus 
[autofocus]="false" //will not focus 

Устаревшие код (старый ответ, на всякий случай):
Я закончил с этим кодом:

import {Directive, ElementRef, Renderer} from '@angular/core'; 

@Directive({ 
    selector: '[autofocus]' 
}) 
export class Autofocus 
{ 
    constructor(private el: ElementRef, private renderer: Renderer) 
    {   
    } 

    ngOnInit() 
    {   
    } 

    ngAfterViewInit() 
    { 
     this.renderer.invokeElementMethod(this.el.nativeElement, 'focus', []); 
    } 
} 

Если я поставлю код в ngOnViewInit он не работает. Код также использует лучшие практики, так как вызов фокуса на элементе напрямую не равен recommended.

Edited (условный автофокусировка):
Несколько дней назад мне нужно было условное автофокус, потому что я скрываю первый элемент автофокусировки и я хочу сосредоточиться другим, но только тогда, когда первый не видно, и я закончил с этим код:

import { Directive, ElementRef, Renderer, Input } from '@angular/core'; 

@Directive({ 
    selector: '[autofocus]' 
}) 
export class AutofocusDirective 
{ 
    private _autofocus; 
    constructor(private el: ElementRef, private renderer: Renderer) 
    { 
    } 

    ngOnInit() 
    { 
    } 

    ngAfterViewInit() 
    { 
     if (this._autofocus || typeof this._autofocus === "undefined") 
      this.renderer.invokeElementMethod(this.el.nativeElement, 'focus', []); 
    } 

    @Input() set autofocus(condition: boolean) 
    { 
     this._autofocus = condition != false; 
    } 
} 

Edited2:
Renderer.invokeElementMethod is deprecated и новый Renderer2 не поддерживает его. Итак, мы вернулись к собственному фокусу (который не работает вне DOM-SSR, например!).

import { Directive, ElementRef, Input } from '@angular/core'; 

@Directive({ 
    selector: '[autofocus]' 
}) 
export class AutofocusDirective 
{ 
    private _autofocus; 
    constructor(private el: ElementRef) 
    { 
    } 

    ngOnInit() 
    { 
     if (this._autofocus || typeof this._autofocus === "undefined") 
      this.el.nativeElement.focus();  //For SSR (server side rendering) this is not safe. Use: https://github.com/angular/angular/issues/15008#issuecomment-285141070) 
    } 

    @Input() set autofocus(condition: boolean) 
    { 
     this._autofocus = condition != false; 
    } 
} 

Прецедент:

[autofocus] //will focus 
[autofocus]="true" //will focus 
[autofocus]="false" //will not focus 
+0

Это то, что я тоже закончил, прочитав это ... http://angularjs.blogspot.co.uk/2016/04/5-rookie-mistakes-to-avoid-with-angular.html – bmd

+1

Я использовал этот код и «OnInit» работали для меня. Мне не пришлось использовать «AfterViewInit». – Rodrigo

+0

@Rodrigo: Я хотел быть уверенным. – Makla

9

Вы можете назначить входной элемент шаблона ссылочную переменную #myInput:

<input type="text" [(ngModel)]="title" #myInput /> 

Пусть ваш компонент реализации AfterViewInit, возьмите ссылку на элемент с ViewChild аннотацию и сосредоточить элемент в ngAfterViewInit крючке:

export class MyComponent implements AfterViewInit { 
    @ViewChild("myInput") 
    private _inputElement: ElementRef; 

    [...] 

    ngAfterViewInit(): void { 
     _inputElement.nativeElement.focus(); 
    } 
} 
+1

Я предпочел бы увидеть базовый подход (атрибут в шаблоне), поэтому мне не нужно писать весь этот код на каждой странице с формой. – Makla

+0

Невозможно прочитать свойство «nativeElement» undefined - Ошибка при запуске на консоли –

+0

@HasmukhBaldaniya Добавлена ​​ли ссылочная переменная шаблона? И вы уверены, что вы получаете доступ к '_inputElement' ** после ** инициализации представления? – rinukkusu

27

autofocus - это встроенная функция html, которая должна работать как минимум для инициализации страницы. Однако он не работает со многими угловыми сценариями, особенно с *ngIf.

Вы можете создать действительно простую настраиваемую директиву для получения желаемого поведения.

import { Directive, OnInit, ElementRef } from '@angular/core'; 

@Directive({ 
    selector: '[myAutofocus]' 
}) 
export class AutofocusDirective implements OnInit { 

    constructor(private elementRef: ElementRef) { }; 

    ngOnInit(): void { 
    this.elementRef.nativeElement.focus(); 
    } 

} 

Вышеуказанная директива работает для моих случаев использования.

Как использовать

<input *ngIf="someCondition" myAutofocus /> 

EDIT: Там, кажется, usecases, где это рано называть фокус в методе OnInit жизненного цикла. Если это так, замените вместо этого OnAfterViewInit.

11

Следующая директива работает для меня, используя угловую 4.0.1

import {Directive, ElementRef, AfterViewInit} from '@angular/core'; 

@Directive({ 
    selector: '[myAutofocus]' 
}) 
export class MyAutofocusDirective implements AfterViewInit { 
    constructor(private el: ElementRef) 
    { 
    } 
    ngAfterViewInit() 
    { 
    this.el.nativeElement.focus(); 
    } 
} 

использовать его как это:

<md-input-container> 
    <input mdInput placeholder="Item Id" formControlName="itemId" name="itemId" myAutofocus> 
</md-input-container> 

вариант использование события OnInit lifecycle не работало r me. Я также попытался использовать Renderer в другом ответе, который не работал для меня.

Смежные вопросы