angulartypescriptstenciljsstencil-component

HTMLCollectionOf is missing the following properties from type 'NodeList'


I've just update from stencil 0 to 1 and I'm getting this error after build my component collection.

[ ERROR ]  TypeScript: ./src\components\layout\tabs\aep-tabs.tsx:24:5
       Type 'HTMLCollectionOf<Element>' is missing the following properties from type 'NodeList': forEach, entries,
       keys, values

 L23:  addTitleEvents() {
 L24:    this.tabTitleElements = this.tabs.getElementsByClassName('tab-title');
 L25:    [].forEach.call(this.tabTitleElements, (tab, pos) => {...

My aep-tabs.tsx file

import { Component, h, Listen, Element, State, Event, Method, EventEmitter } from '@stencil/core';

@Component({
  tag: 'aep-tabs',
  styleUrl: 'aep-tabs-style.scss'
})
export class AepTabs {
  @Element() tabs: HTMLElement;
  @State() initIndex: number = 0;
  @Event() tabClick: EventEmitter;
  private tabsElements;
  private tabsElementList: Array<any> = [];
  private tabTitleElements: NodeList; // <---- HERE

  componentWillLoad() {
    this.createTabsTitles(this.tabs.querySelectorAll('aep-tab'));
  }

  componentDidLoad() {
    this.addTitleEvents();
  }

  addTitleEvents() {

    // ERROR HERE 'this.tabTitleElements' is displaying the error message.
    this.tabTitleElements = this.tabs.getElementsByClassName('tab-title');
    [].forEach.call(this.tabTitleElements, (tab, pos) => {
      tab.addEventListener('click', () => {
        this.tabClick.emit(tab);
        this.activeTabs(pos);
      });
    });
    this.activeTabs(this.initIndex);
  }

  createTabsTitles(tabsList: NodeList) {
    this.tabsElements = tabsList;
    [].forEach.call(this.tabsElements, tab => {
      this.tabsElementList.push(
        <div class="tab-title" data-automation={tab.titletab.toString().toLowerCase()}>
          <span>{tab.titletab}</span>
        </div>
      );
    });
  }
  @Method()
  async activeTabs(index: number) {
    // ERROR HERE 'this.tabTitleElements' is displaying the error message
    this.tabTitleElements = this.tabs.getElementsByClassName('tab-title');
    [].forEach.call(this.tabTitleElements, (tab, pos) => {
      if (index === pos) {
        tab.classList.add('active');
        tab.classList.remove('inactive');
      } else {
        tab.classList.remove('active');
        tab.classList.add('inactive');
      }
    });

    [].forEach.call(this.tabsElements, (tab, pos) => {
      if (index === pos) {
        tab.classList.add('active');
        tab.classList.remove('inactive');
      } else {
        tab.classList.remove('active');
        tab.classList.add('inactive');
      }
    });
  }

  @Listen('clicktab')
  clicktabHandler(event: CustomEvent) {
    this.activeTabs(event.detail);
  }

  render() {
    return (
      <div class="aep-tabs">
        <nav>{this.tabsElementList}</nav>
        <div class="tab-container" data-automation="tab-container">
          <div class="tab-content">
            <slot />
          </div>
        </div>
      </div>
    );
  }
}

tsconfig.json

{
  "compilerOptions": {
    "allowSyntheticDefaultImports": true,
    "allowUnreachableCode": false,
    "declaration": false,
    "experimentalDecorators": true,
    "allowJs": true,
    "lib": ["dom", "es7", "dom.iterable"],
    "moduleResolution": "node",
    "module": "esnext",
    "target": "es2017",
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "jsx": "react",
    "jsxFactory": "h"
  },
  "include": ["src", "types/jsx.d.ts"],
  "exclude": ["node_modules"]
}

Node Version: 10 TSC Version:3.6.3

I've update the "lib", "target", I've also convert the nodeList into an array, but none of them works. Does anyone know how can I fix this issue?


Solution

  • You should replace your code from getElementsByClassName to querySelectorAll

    // this.tabTitleElements = this.tabs.getElementsByClassName('tab-title'); // change this
    this.tabTitleElements = this.tabs.querySelectorAll('.tab-title');