program story

새로 추가 된 입력 요소에 집중

inputbox 2020. 10. 16. 07:23
반응형

새로 추가 된 입력 요소에 집중


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 답변에 참여하여 찾고있는 것과 더 비슷하게 수정합니다.

몇 가지 변경 사항

  • ngForangular2 를 사용하여 직접 수행하는 대신 새 입력을 추가합니다. 주된 목적은 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

업데이트 29/03/2016

시간이 지났고 일이 명확 해졌으며 항상 배우고 가르 칠 모범 사례가 있습니다. 몇 가지를 변경하여이 답변을 단순화했습니다.

  • @ViewChildren그것을 사용 하고 구독하는 대신 새로운 입력이 생성 될 때마다 설치 될 지침을 만들었습니다.
  • RendererWebWorker를 안전하게 만들기 위해 사용 하고 있습니다. 원래 답변 은 권장되지 않는 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 updated to beta 12

Example using ES5 : http://plnkr.co/edit/EpoJvff8KtwXRnXZJ4Rr

Example using ES6/TS : http://plnkr.co/edit/em18uMUxD84Z3CK53RRe

Update 2018

invokeElementMethod is deprecated. Use Renderer2 instead of Renderer.

Give your element an id, and you can use selectRootElement:

this.renderer2.selectRootElement('#myInput').focus();

Take a look at ViewChild, here's a example. This might be what you're looking for:

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();
  }
}

With inline angular code, focus after conditional paint:

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

You can implement a simple input text directive, so that whenever a new input is created, it will auto focus itself. The focus() method is called inside of the ngAfterViewInit() component lifecycle hook after the view is fully initialized.

@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;
      }
    }
}

Use the FocusInput directive in your component:

@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());
    }
}

Note the following:

  1. The (keyup.enter) event is used to detect when the <enter> key is pressed
  2. ngFor is used to repeat the input element for each word from the array of words
  3. last is a Boolean bound to a local variable which is true when the input is the last one
  4. The keyup event is bound to the expression last ? addNewWord() : 0. This ensures that a new input field is only added when the <enter> key is pressed from the last Input

Demo Plnkr


In order to prioritize which element will get focus when initializing several directives in same cycle, use:

Directive:

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

Usage:

<input type="text" focusOnInit="9">

https://plnkr.co/edit/T9VDPIWrVSZ6MpXCdlXF

참고URL : https://stackoverflow.com/questions/34522306/focus-on-newly-added-input-element

반응형