Angular2-구성 요소로드시 텍스트 상자 집중


79

Angular2 (Beta 8)에서 구성 요소를 개발 중입니다. 구성 요소에는 텍스트 상자와 드롭 다운이 있습니다. 구성 요소가로드되거나 드롭 다운의 변경 이벤트가 발생하자마자 텍스트 상자에 포커스를 설정하고 싶습니다. angular2에서 이것을 어떻게 얻을 수 있습니까? 다음은 구성 요소에 대한 Html입니다.

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

답변:


78

간단한 autofocusHTML5 속성을 사용하면 '로드시'시나리오에서 작동합니다.

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

또는

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

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


45
이것은 페이지를 새로 고치거나 페이지를 처음부터로드하는 경우에만 작동하는 것 같습니다. 라우터를 통해 양식 구성 요소로 이동하면 필드가 선택되지 않습니다.
Dennis W

3
이것은 우리가 여러 구성 요소가 좋은 해결책이 아니다, 이것은 첫 번째 기본 구성 요소에 대해 작동합니다
Paresh Varde

+1-Nikhil 감사합니다. 완벽합니다. 나는 이것을 이렇게 사용한다 : <div class = "or-name uk-tile-muted uk-text-left uk-display-block"* ngIf = "value! == cHttpUser"> {{value.name}} </ div> <input class = "uk-input uk-form-controls-text or-input"* ngIf = "value === cHttpUser"[(ngModel)] = "value.name"autofocus (click) = "update ( ) "(keyup.enter) ="update () "(keyup.tab) ="update () "(blur) ="update () "> : div를 클릭하고 아래에 입력하면 한 번에 초점을 맞출 수 있습니다. 들어가서 입력하려면 다시 클릭해야했지만 "반쪽"이었습니다. 한 번의 클릭이 남았습니다!
Olivier

78

이 답변은 Angular 2 게시물에서 영감을 얻었습니다 . 새로 추가 된 입력 요소에 중점을 둡니다.

Angular2에서 Html 요소에 포커스를 설정하는 단계

  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
간단하지만 다른 구성 요소에 포커스를 설정해야하는 경우 어떻게됩니까? 예를 들어 하위 구성 요소의 기본 검색 상자 (헤더에 있음)입니다.
Rick Strahl

2
동적으로 생성 된 요소는 어떻습니까?
Kaushik Thanki

Angular Material을 사용 ChangeDetectorRef하여 생성자 에 포함 한 다음 @jspassov 의이 답변에this.cd.detectChanges(); 따라 포커스 호출 후 호출 해야했습니다 .
Derek Hill

32
<input id="name" type="text" #myInput />
{{ myInput.focus() }}

입력이 생성 된 후 "myInput.focus ()"코드가 실행 되기 때문에 이것이 가장 좋고 간단한 방법 입니다.

경고 :이 솔루션은 양식에 단일 요소가있는 경우에만 허용됩니다 (사용자가 다른 요소를 선택할 수 없음).


3
실제로 작동하는 롤! A는 감사 해키하지만, 아주 단순하고 기능 비트 :!
바그너 단다 다 실바 필류에게

5
처음에는 많이 좋아했지만 항상 다른 요소를 선택하거나 복사 할 텍스트를 강조 표시하지 못하게하는 것 같습니다. 보기 아이들과 함께 여기에서 받아 들여지는 대답으로 전환해야했습니다.
Jason W

4
네, 화면에 편집이 하나만있는 경우이 방법을 사용할 수 있습니다. 다른 입력에 초점을 맞추는 것을 방지합니다!
Sergey

1
myInput.focus () 메서드는 모든 변경주기에서 실행됩니다. 이로 인해 @JasonW와 같은 원치 않는 동작이 발생할 수 있습니다.
Carsten

2
숨겨진 보석 !! :) 당신은 내 친구를 흔들어!
마니 쉬자인

29

원래 질문은 이벤트에 대한 응답으로 처음에 포커스를 설정하거나 나중에 포커스를 설정하는 방법을 요청했습니다. 이에 접근하는 올바른 방법은 모든 입력 요소에 대해 설정할 수있는 속성 지시문을 만든 다음 사용자 지정 이벤트를 사용하여이 입력 요소에 대한 포커스 메서드를 안전하게 트리거하는 것 같습니다. 그렇게하려면 먼저 지시문을 작성하십시오.

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', []);
        });
    }
}

웹 작업자에게 안전한 nativeElement에서 renderer.invokeElementMethod를 사용합니다. focusEvent가 입력으로 선언된다는 점에 유의하십시오.

그런 다음 새 지시문을 사용하여 입력 요소에 포커스를 설정하려는 템플릿이있는 Angular 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';

이 구성 요소의 템플릿에서 다음과 같이 새 [focus] 속성을 설정합니다.

<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를 방출하게하고,이 이미 터를 템플릿의 input 요소에있는 [focus] 속성에 할당했기 때문에이 EventEmitter를 새 지시문에 대한 입력으로 선언하고 포커스를 호출했습니다. 이 이벤트에 대한 구독에 전달한 화살표 함수의 메서드를 사용하면 구성 요소가 초기화 된 후 setFocus가 호출 될 때마다 입력 요소가 포커스를받습니다.

내 앱에서도 동일한 요구 사항이 있었으며 광고 된대로 작동했습니다. 다음에 대단히 감사합니다 : http://blog.thecodecampus.de/angular-2-set-focus-element/


이것은 훌륭하고 작동하지만 사소한 초점을 맞추기에는 너무 많은 작업이 아닌지 궁금합니다. 요구 사항이 아니기 때문에 사용자에게 좋은 일로하려고했지만 사용자를 한 번의 클릭으로 저장하기위한 과도한 양의 코드처럼 보입니다.
Ka Mok

3
@KentWeigel-이것은 정말 고상한 솔루션이며 완벽하게 작동합니다. '올바른'대답입니다. 감사.
HockeyJ

이것은 정말 좋은 솔루션입니다,하지만 당신은 사용하지 않는 setFocus기능
하칸 Fıstık


2

나는 약간 다른 문제가 있었다. 모달 에서 입력으로 작업했습니다. 했고 그것은 나를 미치게 만들었다. 제안 된 솔루션 중 어느 것도 저에게 효과가 없었습니다.

이 문제를 발견 할 때까지 : https://github.com/valor-software/ngx-bootstrap/issues/1597

이 좋은 녀석은 ngx-bootstrap 모달 에 포커스 구성이 . 이 구성이 false로 설정되지 않은 경우 모달은 애니메이션 후에 초점이 맞춰지고 다른 것에 초점을 맞출 방법이 없습니다.

최신 정보:

이 구성을 설정하려면 모달 div에 다음 속성을 추가하십시오.

[config]="{focus: false}"

업데이트 2 :

입력 필드에 초점을 맞추기 위해 지시문을 작성하고 입력 필드에 ng-untouched 클래스가있는 한 모든 AfterViewChecked주기에서 초점을 설정했습니다.

 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', []);
    }
}

@FireGnome 안녕하세요, 이것을 구성 할 위치를 공유 할 수 있습니까?
cyberabis

여기에서 볼 수 있듯이 : valor-software.com/ngx-bootstrap/#/modals#static 구성 속성이 있습니다 [config] = "{backdrop : 'static'}"속성 포커스를 설정할 수 있습니다. false
FireGnome

안녕하세요, 같은 문제가 있습니다 .ngx 모달 및 구성을 추가하고 지시문 (아직 운이 없음)으로 포커스를 추가하려고했습니다. 매번 입력에 포커스를 추가하는 데 무엇을 사용 했습니까? 감사합니다
Simon

2

또한 이렇게 동적으로 수행 할 수 있습니다.

<input [id]="input.id" [type]="input.type" [autofocus]="input.autofocus" />

입력이있는 곳

const input = {
  id: "my-input",
  type: "text",
  autofocus: true
};

반대는 나를 위해 작동하지 않았다[autofocus]="false"
의 teddybear

귀하의 경우에는 autofocus =“false”입니다. []는 "myObj.key"와 같은 평가 전용입니다. 실제 문자열을 사용하고 있습니다.
SoEzPz

2

autoFocus 첫 번째 필드에 대한 지침

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

@Directive({
  selector: "[appFocusFirstEmptyInput]"
})
export class FocusFirstEmptyInputDirective implements AfterViewInit {
  constructor(private el: ElementRef) {}
  ngAfterViewInit(): void {
    const invalidControl = this.el.nativeElement.querySelector(".ng-untouched");
    if (invalidControl) {
      invalidControl.focus();
    }
  }
}


0

나는 모든 브라우저에서 이러한 솔루션 중 많은 것을 운이 좋지 않았습니다. 이것은 나를 위해 일한 솔루션입니다.

라우터 변경 :

router.events.subscribe((val) => {
    setTimeout(() => {
        if (this.searchElement) {
            this.searchElement.nativeElement.focus();
        }
    }, 1);
})

그런 다음 온로드 ngAfterViewInit()시나리오입니다.


0

$ (jquery) 사용할 수 있습니다.

<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="txtname`enter code here`" 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>

그런 다음 ts에서 :

    declare var $: any;

    @Component({
      selector: 'app-my-comp',
      templateUrl: './my-comp.component.html',
      styleUrls: ['./my-comp.component.css']
    })
    export class MyComponent  {

    @ViewChild('loadedComponent', { read: ElementRef, static: true }) loadedComponent: ElementRef<HTMLElement>;

    setFocus() {
    const elem = this.loadedComponent.nativeElement.querySelector('#txtname');
          $(elem).focus();
    }
    }

@ViewChild를 사용하는 유일한 사람에게는 +1하지만 이미 요소 (또는 컨테이너)에 대한 참조가있는 경우 jquery가 필요하지 않습니다.
Nieminen
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.