使用QueryList访问ContentChildren内部的HTMLButtonElement

时间:2020-06-15 14:32:32

标签: angular

我正在尝试访问具有HTMLButtonElement但没有获取按钮元素的组件内部的ng-content

TestComponent

@Component({
selector: 'app-test',
template: `<div>
              <ng-content select="button"></ng-content>
           </div>`
})
export class TestComponent implements AfterContentInit {

@ContentChildren(HTMLButtonElement)
buttons: QueryList<HTMLButtonElement>;

    ngAfterContentInit() {
        this.buttons.forEach(x => { //this.buttons.length is always 0
         x.classList.add('btn-primary');
        });
    }
}

用法:

<app-test>
    <button>Button1</button>
    <button>Button2</button>
</app-multi-action-button>

2 个答案:

答案 0 :(得分:2)

Stackblitz demo

根据the docs@ContentChildren()搜索“指令类型或用于查询的名称” 。这意味着它仅适用于@Component@Directive装饰的元素,或标有模板引用变量的元素(这些都不适用于您的情况)。

您可以做的是将div标记为容器,然后使用浏览器的本机API在其中查找按钮。

<div #container>
  <ng-content select="button"></ng-content>
</div>
@ViewChild('container', {static: true}) containerDiv: ElementRef;

ngAfterContentInit() {
  const buttons = this.containerDiv.nativeElement.querySelectorAll("button");
  buttons.forEach(x => x.classList.add("btn-primary"));
}

enter image description here

另一种方法:MutationObserver

出于好奇:如果没有{static: true}参数,我们该怎么办?

浏览器API中有一个叫做MutationObserver的东西。每当DOM的选定部分在各个方面(属性,节点,值)甚至整个文档发生更改时,您都可以注册要调用的回调。

请牢记以下步骤,我们可以在此处完成MutationObserver的帮助(请检查其他Stackblitz demo):

第1步:创建在观察对象中发生某些更改时要调用的函数。
export function buttonsObserverCallback(
  mutationsList: MutationRecord[],
  observer: any
) {
  mutationsList.map(m => m.addedNodes).forEach(n => {
    n.forEach(no => console.log(no))
  });
  // Use traditional 'for loops' for IE 11
  for (let i = 0; i < mutationsList.length; i++) {
    if (
      mutationsList[i].type === "childList" &&
      mutationsList[i].addedNodes.length
    ) {
      mutationsList[i].addedNodes.forEach((node: Node) => {
        if (node instanceof HTMLButtonElement) {
          const $button = node as HTMLButtonElement;
          if (!$button.classList.contains("btn-primary")) {
            $button.classList.add("btn-primary");
          }
        }
      });
    }
  }
}
第2步:创建一个Mutation观察器的实例,并向其注册上述回调
private _mutationObserver = new MutationObserver(buttonsObserverCallback);
第3步:获取角度分量的实例并进行注册以供观察
constructor(private el: ElementRef) {
  this._mutationObserver.observe(el.nativeElement, {
    childList: true,
    subtree: true, // observe the descendants too
  });
}
第4步:不要忘记最后释放观察者
ngOnDestroy() {
  this._mutationObserver.disconnect();
}

答案 1 :(得分:1)

我不确定要查询HTMLButtonElement,但是您可以尝试将模板引用变量分配给元素。尝试以下

parent.component.html

<app-test>
  <button #button>Button1</button>
  <button #button>Button2</button>
</app-test>

test.component.ts

export class TestComponent implements AfterContentInit {
  @ContentChildren('button')
  buttons: QueryList<any>;

  ngAfterContentInit() {
    this.buttons.forEach(x => {
      console.log(x);
      x.nativeElement.classList.add('btn-primary');
    });
  }
}

工作示例:Stackblitz