2016-03-04 3 views
32

Я разрабатываю компонент в Angular2 (Beta 8). Компонент имеет текстовое поле и выпадающее меню. Я хотел бы установить фокус в текстовом поле, как только компонент будет загружен, или в случае изменения выпадающего списка. Как я могу достичь этого в угловой2. Ниже приведен Html для компонента.Angular2 - Фокусировка текстового поля на нагрузке компонента

<div> 
 
    <form role="form" class="form-horizontal ">   
 
     <div [ngClass]="{showElement:IsEditMode, hidden:!IsEditMode}"> 
 
      <div class="form-group"> 
 
       <label class="control-label col-md-1 col-sm-1" for="name">Name</label> 
 
       <div class="col-md-7 col-sm-7"> 
 
        <input id="name" type="text" [(ngModel)]="person.Name" class="form-control" /> 
 

 
       </div> 
 
       <div class="col-md-2 col-sm-2"> 
 
        <input type="button" value="Add" (click)="AddPerson()" class="btn btn-primary" /> 
 
       </div> 
 
      </div> 
 
     </div> 
 
     <div [ngClass]="{showElement:!IsEditMode, hidden:IsEditMode}"> 
 
      <div class="form-group"> 
 
       <label class="control-label col-md-1 col-sm-1" for="name">Person</label> 
 
       <div class="col-md-7 col-sm-7"> 
 
        <select [(ngModel)]="SelectedPerson.Id" (change)="PersonSelected($event.target.value)" class="form-control"> 
 
         <option *ngFor="#item of PeopleList" value="{{item.Id}}">{{item.Name}}</option> 
 
        </select> 
 
       </div> 
 
      </div> 
 
     </div>   
 
    </form> 
 
</div>

ответ

33

Этот ответ вдохновлен пост Angular 2: Focus on newly added input element

шаги, чтобы установить фокус на Html элемент в Angular2

  1. Импорт ViewChildren в вашем компоненте

    import { Input, Output, AfterContentInit, ContentChild,AfterViewInit, ViewChild, ViewChildren } from 'angular2/core'; 
    
  2. Объявить локального шаблона имя переменной для html, для которого вы хотите установить фокус

  3. Реализовать функцию ngAfterViewInit() или других соответствующих крюки жизненного цикла
  4. Ниже приведен фрагмент кода, который я использовал для настройки фокуса

    ngAfterViewInit() {vc.first.nativeElement.focus()} 
    
  5. Добавить #input атрибут к элементу DOM вы хотите получить доступ ,

///This is typescript 
 
import {Component, Input, Output, AfterContentInit, ContentChild, 
 
    AfterViewChecked, AfterViewInit, ViewChild,ViewChildren} from 'angular2/core'; 
 

 
export class AppComponent implements AfterViewInit,AfterViewChecked { 
 
    @ViewChildren('input') vc; 
 
    
 
    ngAfterViewInit() {    
 
     this.vc.first.nativeElement.focus(); 
 
    } 
 
    
 
}
<div> 
 
    <form role="form" class="form-horizontal ">   
 
     <div [ngClass]="{showElement:IsEditMode, hidden:!IsEditMode}"> 
 
      <div class="form-group"> 
 
       <label class="control-label col-md-1 col-sm-1" for="name">Name</label> 
 
       <div class="col-md-7 col-sm-7"> 
 
        <input #input id="name" type="text" [(ngModel)]="person.Name" class="form-control" /> 
 

 
       </div> 
 
       <div class="col-md-2 col-sm-2"> 
 
        <input type="button" value="Add" (click)="AddPerson()" class="btn btn-primary" /> 
 
       </div> 
 
      </div> 
 
     </div> 
 
     <div [ngClass]="{showElement:!IsEditMode, hidden:IsEditMode}"> 
 
      <div class="form-group"> 
 
       <label class="control-label col-md-1 col-sm-1" for="name">Person</label> 
 
       <div class="col-md-7 col-sm-7"> 
 
        <select [(ngModel)]="SelectedPerson.Id" (change)="PersonSelected($event.target.value)" class="form-control"> 
 
         <option *ngFor="#item of PeopleList" value="{{item.Id}}">{{item.Name}}</option> 
 
        </select> 
 
       </div> 
 
      </div> 
 
     </div>   
 
    </form> 
 
</div>

+2

Простой, но что произойдет, если вам нужно установить фокус в другом компоненте?Например, окно поиска по умолчанию (в заголовке) из дочернего компонента. –

+1

Как насчет динамически генерируемого элемента? –

4

См Angular 2: Focus on newly added input element о том, как установить фокус.

Для «нагрузка» используйте обратный вызов жизненного цикла .

+0

Большое спасибо. Ссылка, которую вы поделили, была весьма полезна. +1 для этого. Поделится ответом на этот конкретный сценарий. – parag

15

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

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

@Directive({ 
    selector: '[focus]' 
}) 
export class FocusDirective { 
    @Input('focus') focusEvent: EventEmitter<boolean>; 

    constructor(@Inject(ElementRef) private element: ElementRef, private renderer: Renderer) { 
    } 

    ngOnInit() { 
     this.focusEvent.subscribe(event => { 
      this.renderer.invokeElementMethod(this.element.nativeElement, 'focus', []); 
     }); 
    } 
} 

Обратите внимание, что она использует renderer.invokeElementMethod на nativeElement, который является веб-рабочий сейф. Также обратите внимание, что focusEvent объявляется как вход.

Затем добавьте следующие объявления в угловой 2 компонент, который имеет шаблон, где вы хотите использовать новую директиву, чтобы установить фокус на элемент ввода:

public focusSettingEventEmitter = new EventEmitter<boolean>(); 

ngAfterViewInit() { // ngOnInit is NOT the right lifecycle event for this. 
    this.focusSettingEventEmitter.emit(true); 
} 
setFocus(): void { 
    this.focusSettingEventEmitter.emit(true); 
} 

Не забудьте импортировать EventEmitter выше компонент, как это:

import { Component, EventEmitter } from '@angular/core'; 

и в шаблоне для этого компонента, установите новый [фокус] атрибута, как это:

<input id="name" type="text" name="name" 
    [(ngModel)]="person.Name" class="form-control" 
    [focus]="focusSettingEventEmitter"> 

Наконец, в вашем модуле, импорта и объявить новую директиву, как это:

import { FocusDirective } from './focus.directive'; 

@NgModule({ 
    imports: [ BrowserModule, FormsModule ], 
    declarations: [AppComponent, AnotherComponent, FocusDirective ], 
    bootstrap: [ AppComponent ] 
}) 

Резюмируя: функция ngAfterViewInit вызовет новый EventEmitter излучать, и с тех пор мы присвоили этот эмиттер [внимание] атрибут в элементе ввода в нашем шаблоне, и мы объявили этот EventEmitter как вход в новую директиву и вызвали метод фокуса в функции стрелки, который мы передали подписке на это событие, элемент ввода получит фокус после того, как компонент инициализируется, и всякий раз, когда вызывается setFocus.

У меня была такая же потребность в моем собственном приложении, и это работало как рекламируемое. Большое спасибо к следующему: http://blog.thecodecampus.de/angular-2-set-focus-element/

+0

Это замечательно, и это работает, но я задаюсь вопросом, не слишком ли слишком много работы для незначительной фокусировки. Я собирался сделать это как приятную вещь для пользователя, поскольку это не требование, но это кажется чрезмерным количеством кода для сохранения пользователя одним кликом. –

34

Используя простой атрибут autofocus HTML5 работает для сценария 'под нагрузкой'

<input autofocus placeholder="enter text" [(ngModel)]="test"> 

или

<button autofocus (click)="submit()">Submit</button> 

http://www.w3schools.com/TAgs/att_input_autofocus.asp

+13

Это похоже на работу, если вы обновите страницу или загрузите страницу с нуля. Если вы перейдете к компоненту формы через маршрутизатор, поле не будет выбрано. –

+4

это безупречный. Зачем убивать мух с помощью пушки? : D –

+0

Это нехорошее решение, когда у нас есть несколько компонентов, это будет работать только для первого компонента по умолчанию –

2

У меня была немного другая проблема. Я работал со входом в модальным, и это сводило меня с ума. Никакие предлагаемые решения не работали для меня.

Пока я не нашел этот вопрос: https://github.com/valor-software/ngx-bootstrap/issues/1597

Это хороший парень дал мне намек, что NGX-бутстраповской модальную имеет конфигурацию фокусировки. Если эта конфигурация не установлена ​​в значение false, модальность будет сфокусирована после анимации, и нет НИКАКИХ способов сосредоточить что-либо еще.

Update:

Чтобы установить эту конфигурацию, добавьте следующий атрибут модальной DIV:

[config]="{focus: false}" 

Update 2:

Чтобы заставить фокус на поле ввода Я написал директиву и задал фокус в каждом цикле AfterViewChecked, если поле ввода имеет класс ng-нетронутый.

ngAfterViewChecked() { 
    // This dirty hack is needed to force focus on an input element of a modal. 
    if (this.el.nativeElement.classList.contains('ng-untouched')) { 
     this.renderer.invokeElementMethod(this.el.nativeElement, 'focus', []); 
    } 
} 
+0

Привет @FireGnome, можете ли вы поделиться, где его настроить? – cyberabis

+0

, как вы можете увидеть здесь: http://valor-software.com/ngx-bootstrap/#/modals#static есть атрибут конфигурации [CONFIG] = "{Фоновое изображение: 'статический'}" You может установить там фокус свойства: false – FireGnome

+0

Привет, У меня такая же проблема, я добавил мода и конфигурацию ngx и попытался добавить фокус с директивой (пока не повезло), что вы использовали, чтобы добавить фокус в вводить каждый раз? благодаря – Simon

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

  • Нет связанных вопросов^_^