Как получить конкретный элемент в ViewChildren QueryList как ElementRef при фильтрации по свойству (свойствам)? - PullRequest
0 голосов
/ 06 октября 2019

Я пытаюсь установить фокус на любой заданный вход после того, как этот вход изменится (или потенциально манипулировать тем же элементом DOM другими способами). Я использую Reactive Forms, и элементы Form отображаются динамически.

Проблема, с которой я столкнулся, заключается в том, что я могу получить доступ к элементу, который был изменен, либо с помощью @ViewChildren(AppTag) ipt!: QueryList<AppTag>, что позволяет мне фильтровать нужный элемент,но тогда я не знаю, как получить этот элемент, используя nativeElement, или я могу использовать @ViewChildren(AppTag) ipt!: QueryList<ElementRef>, что (удивительно), кажется, позволяет мне фильтровать рассматриваемый элемент, но (также удивительно), я все еще не могуманипулировать элементом DOM. В любом случае я получаю ошибку: "itm.nativeElement is undefined".

Чтобы воспроизвести ошибку, введите любое значение в один из Inputs в следующем StackBlitz , а затем TAB outзаписи. Вы увидите ошибку в консоли.

Ниже приведены соответствующие фрагменты кода, но, пожалуйста, поэкспериментируйте с полным примером StackBlitz, чтобы более четко увидеть шаблон и структуру данных:

app.component.ts

export class AppComponent implements OnInit {
  @ViewChildren(AppTag) ipt !: QueryList<ElementRef>
  name = 'Angular';
  formCtls: any = {};
  form: FormGroup = new FormGroup({});
  data: {} = { // raw data
    name: 
    {
      first: {values: [""], label: "first name"},
      middle: {values: [""], label: "middle name"},
      last: {values: [""], label: "last name"}
    } 
  };
  dispData: any[] = []; // Data formatted for display/iteration by template
  itmNo: number = 0; // Unique ID for each Input
  focusItm = 0; // The bridge by which "FormControl.valueChanges" communicates with "QueryList.changes"

. . . 
. . .

  ngAfterViewInit() {
    this.ipt.changes.subscribe(list=>{
      setTimeout(()=>
        list.filter(itm=>+itm.id===this.focusItm).forEach(itm=>{
          console.log(`Item: ${itm.id} Focus: ${this.focusItm} ${+itm.id===this.focusItm}`);
          itm.nativeElement.focus();  // <-- HERE'S WHERE I'M HAVING THE TROUBLE
        }  
    ),0)}
    )
  }

. . . 
. . .


  renderDisplayArray(){
    this.dispData = [];
    this.itmNo = 0;

. . . 
. . .

          const i=r;
          this.formCtls[ctlName] = new FormControl(itm["values"][r], {updateOn: 'blur'});
          this.form.addControl(ctlName,this.formCtls[ctlName]);
          const curItm=this.itmNo;

          this.formCtls[ctlName].valueChanges.subscribe(val=>{
            console.log(`VALUE: ${val}`);
            itm["values"][i]=val || '';
            this.renderDisplayArray();
            this.focusItm = curItm;

          })
. . . 
. . .

Вот директива AppTag, которую я применяю к входам, чтобы иметь возможность filter и захватывать нужные мне элементы DOM. appTag.ts

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

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

export class AppTag implements OnInit{

constructor(private el: ElementRef) {}
@Input('appTag') id: number;

}

1 Ответ

1 голос
/ 06 октября 2019

Просто измените видимость с el: ElementRef в AppTag на общедоступную

@Directive({
  selector: '[appTag]'
})
export class AppTag implements OnInit{
   constructor(public el: ElementRef) {}
   @Input('appTag') id: number;
}

и используйте в функции фильтра свойство el AppTag.

ИзменитьВаша проблема в строке:

itm.el.nativeElement.focus();  // <-- HERE'S WHERE I'M HAVING THE TROUBLE
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...