Подтвердить что ты не робот

Angular2 + входной элемент автофокуса

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

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

Поддерживает ли Angular2 встроенную поддержку этой функции?

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

4b9b3361

Ответ 1

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

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 вызывать фокус на элементе напрямую.

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

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 устарел, и новый 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

Ответ 2

autofocus - это встроенная функция html, которая должна работать как минимум для инициализации страницы. Однако он не работает со многими сценариями angular, особенно с *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 />

РЕДАКТИРОВАТЬ: Кажется, что в режиме OnInit жизненного цикла есть время, когда нужно называть фокус. Если это так, замените вместо OnAfterViewInit.

Ответ 3

Следующая директива работает для меня с помощью Angular 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 не работала для меня. Я также попытался использовать Renderer в другом ответе, который не работал у меня.

Ответ 4

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

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

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

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

    [...]

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

Ответ 5

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

просто добавьте {{myInput.focus()}} сразу после ввода внутри шаблона

Ответ 6

Если вам не нужна функция true/false, но вы хотите, чтобы автофокус всегда был установлен, то у Makla есть более короткая реализация:

autofocus.directive.ts:

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

@Directive({
    selector: '[autofocus]'
})

export class AutofocusDirective implements AfterViewInit {

    constructor(private el: ElementRef) {
    }

    ngAfterViewInit() {
        // Otherwise Angular throws error: Expression has changed after it was checked.
        window.setTimeout(() => {
            this.el.nativeElement.focus();
        });
    }
}

вариант использования:

<input autofocus> //will focus

При использовании AfterViewInit вместо OnInit курсор помещается после содержимого внутри поля ввода, если оно будет заполнено.

Не забудьте объявить и экспортировать вашу директиву в свой модуль!