input
상자 목록이있는 새로운 Angular 2 앱이 있습니다. 사용자가 리턴 키를 누르면 input
현재 편집중인 상자 바로 뒤에 새 상자를 추가합니다 . 또는 오히려 (비동기 적으로) 모델의 배열에 새 항목을 추가하여 Angular 2가 input
가까운 장래에 자동으로 새 상자를 생성합니다 .
어떻게이 정도로 할 수 input
초점을 자동으로 새로 추가 된 요소로 변경?
편집 1 :
또는 DOM을 생성하는 모델 개체에 대한 참조를 얻습니다. 컴포넌트 코드에서 특정 모델 객체를 나타내는 DOM 요소를 검색하는 방법이 있습니까?
편집 2 :
다음은이 작업을 수행하는 코드입니다. 바라건대 이것은 일부 Angular 2 개발자에게 답장을 장려하기에 충분히 공격적입니다. 🙂
app.WordComponent = ng.core
.Component({
selector: 'word-editor',
template:'<input type="text" [value]="word.word" (input)="word.update($event.target.value)" (keydown)="keydown($event)"/>',
styles:[
''
],
properties:[
'list:list',
'word:word'
]
})
.Class({
constructor:[
function() {
}
],
keydown:function(e) {
if(e.which == 13) {
var ul = e.target.parentNode.parentNode.parentNode;
var childCount = ul.childNodes.length;
this.list.addWord("").then(function(word) {
var interval = setInterval(function() {
if(childCount < ul.childNodes.length) {
ul.lastChild.querySelector('input').focus();
clearInterval(interval);
}
}, 1);
});
}
}
});
답변
그렇게 할 수 있다면 @Sasxa 답변에 참여하여 찾고있는 것과 더 비슷하게 수정하겠습니다.
몇 가지 변경 사항
ngFor
angular2 를 사용하여 직접 수행하는 대신 새 입력을 추가합니다. 주된 목적은 angular2를 만들어 그것을 반복하는 것입니다.- 대신 속성 이있는 QueryList 를 반환하는
ViewChild
것을 사용할 것ViewChildren
입니다 . 이 속성은 Observable이며 변경된 요소를 반환합니다.changes
ES5에서는 데코레이터가 없기 때문에 queries
속성을 사용하여ViewChildren
구성 요소
Component({
selector: 'cmp',
template : `
<div>
// We use a variable so we can query the items with it
<input #input (keydown)="add($event)" *ngFor="#input of inputs">
</div>
`,
queries : {
vc : new ng.core.ViewChildren('input')
}
})
마지막 요소에 초점 을 맞 춥니 다 .
ngAfterViewInit: function() {
this.vc.changes.subscribe(elements => {
elements.last.nativeElement.focus();
});
}
앞서 말했듯이 ViewChildren은 changes
속성 이 포함 된 QueryList를 반환 합니다. 변경할 때마다 구독하면 요소 목록이 반환됩니다. 목록 elements
포함 last
이 경우 마지막 요소를 반환, 우리가 사용하는 (다른 사람의 사이에서) 속성을 nativeElement
마침내과focus()
입력 요소 추가 이것은 순수한 편의를위한 것이며, 입력 배열은 ngFor
.
add: function(key) {
if(key.which == 13) {
// See plnkr for "this.inputs" usage
this.inputs.push(this.inputs.length+1);
}
}
배열에 더미 항목을 푸시하여 다시 그립니다.
ES5 사용 예 : http://plnkr.co/edit/DvtkfiTjmACVhn5tHGex
ES6 / TS 사용 예 : http://plnkr.co/edit/93TgbzfPCTxwvgQru2d0?p=preview
2016 년 3 월 29 일 업데이트
시간이 지났고 상황이 명확 해졌으며 항상 배우고 가르 칠 모범 사례가 있습니다. 몇 가지를 변경하여이 답변을 단순화했습니다.
@ViewChildren
그것을 사용 하고 구독하는 대신 새로운 입력이 생성 될 때마다 설치 될 지침을 만들었습니다.Renderer
WebWorker를 안전하게 만들기 위해 사용 하고 있습니다. 원래 답변 은 권장되지 않는focus()
에 직접 액세스 합니다nativeElement
.- 이제
keydown.enter
키 다운 이벤트를 단순화하는 것을 듣고which
값 을 확인할 필요가 없습니다 .
요점. 구성 요소는 다음과 같습니다 (아래 plnkr의 단순화 된 전체 코드).
@Component({
template: `<input (keydown.enter)="add()" *ngFor="#input of inputs">`,
})
add() {
this.inputs.push(this.inputs.length+1);
}
그리고 지침
@Directive({
selector : 'input'
})
class MyInput {
constructor(public renderer: Renderer, public elementRef: ElementRef) {}
ngOnInit() {
this.renderer.invokeElementMethod(
this.elementRef.nativeElement, 'focus', []);
}
}
보시다시피 요소에 직접 액세스하는 대신 invokeElementMethod
트리거 focus
를 호출 하고 있습니다.
이 버전은 원래 버전보다 훨씬 깨끗하고 안전합니다.
plnkrs가 베타 12로 업데이트되었습니다.
ES5 사용 예 : http://plnkr.co/edit/EpoJvff8KtwXRnXZJ4Rr
ES6 / TS 사용 예 : http://plnkr.co/edit/em18uMUxD84Z3CK53RRe
2018 업데이트
invokeElementMethod
더 이상 사용되지 않습니다. Renderer 대신 Renderer2를 사용하세요.
요소에 ID를 부여하면 selectRootElement 를 사용할 수 있습니다 .
this.renderer2.selectRootElement('#myInput').focus();
답변
ViewChild를 살펴보십시오 . 여기에 예제가 있습니다. 이것은 당신이 찾고있는 것일 수 있습니다.
import {Component, ViewChild} from 'angular2/core'
@Component({
selector: 'my-app',
providers: [],
template: `
<div>
<input #name>
</div>
`,
directives: []
})
export class App {
@ViewChild('name') vc: ElementRef;
ngAfterViewInit() {
this.vc.nativeElement.focus();
}
}
답변
인라인 각도 코드를 사용하여 조건부 페인트 후에 초점을 맞 춥니 다.
<span *ngIf="editId==item.id">
<input #taskEditText type="text" [(ngModel)]="editTask" (keydown.enter)="save()" (keydown.esc)="saveCancel()"/>
<button (click)="save()">Save</button>
<button (click)="saveCancel()">Cancel</button>
{{taskEditText.focus()}}
</span>
답변
간단한 입력 텍스트 지시문을 구현하여 새 입력이 생성 될 때마다 자동으로 초점을 맞출 수 있습니다. 이 focus()
메서드는 ngAfterViewInit()
뷰가 완전히 초기화 된 후 구성 요소 수명주기 후크 내에서 호출됩니다 .
@Directive({
selector: 'input[type=text]'
})
export class FocusInput implements AfterViewInit {
private firstTime: bool = true;
constructor(public elem: ElementRef) {
}
ngAfterViewInit() {
if (this.firstTime) {
this.elem.nativeElement.focus();
this.firstTime = false;
}
}
}
FocusInput
구성 요소 에서 지시문을 사용하십시오 .
@Component({
selector: 'app',
directives: [FocusInput],
template: `<input type="text" (keyup.enter)="last ? addNewWord():0"
*ngFor="#word of words; #last = last" [value]="word.word"
#txt (input)="word.word = txt.value" />{{words |json}}`
})
export class AppComponent {
words: Word[] = [];
constructor() {
this.addNewWord();
}
addNewWord() {
this.words.push(new Word());
}
}
다음 사항에 유의하십시오.
(keyup.enter)
이벤트는 <입력> 때를 감지하는 데 사용되는 키를 누를 때ngFor
배열의 각 단어에 대해 입력 요소를 반복하는 데 사용됩니다.words
last
입력이 마지막 일 때 참인 지역 변수에 바인딩 된 부울입니다.- keyup 이벤트는 표현식에 바인딩됩니다
last ? addNewWord() : 0
. 이렇게하면 마지막 입력에서 <enter> 키를 눌렀을 때만 새 입력 필드가 추가됩니다.
답변
동일한주기에서 여러 지시문을 초기화 할 때 어떤 요소에 초점을 맞출 지 우선 순위를 지정하려면 다음을 사용하십시오.
지령:
@Directive({
selector: '[focusOnInit]'
})
export class FocusOnInitDirective implements OnInit, AfterViewInit {
@Input('focusOnInit') priority: number = 0;
static instances: FocusOnInitDirective[] = [];
constructor(public renderer: Renderer, public elementRef: ElementRef) {
}
ngOnInit(): void {
FocusOnInitDirective.instances.push(this)
}
ngAfterViewInit(): void {
setTimeout(() => {
FocusOnInitDirective.instances.splice(FocusOnInitDirective.instances.indexOf(this), 1);
});
if (FocusOnInitDirective.instances.every((i) => this.priority >= i.priority)) {
this.renderer.invokeElementMethod(
this.elementRef.nativeElement, 'focus', []);
}
}
}
용법:
<input type="text" focusOnInit="9">