如何解决Cannot read 属性 'nativeElement' of undefined in angular when using viewchild ElementRef

How to solve Cannot read property 'nativeElement' of undefined in angular when using viewchild ElementRef

您好,我正在使用 ViewChild 获取 Angular 中的 DOM 个元素,但出现如下错误: 未读取 属性 'nativeElement' 未定义 我调试了一段时间,但仍在苦苦挣扎。 谁能指出为什么它不起作用?

html:

<div>
    <label>
        Filter nodes
        <select #nodeFilterSelect>
          <option value=''>All characters</option>
          <option value='kid'>kids</option>
          <option value='adult'>adults</option>
          <option value='male'>male</option>
          <option value='female'>female</option>
        </select>
    </label>

    <br>
    <br>
    <label>
      Filter edges
      <div>
        <label>
          <input type='checkbox' #edgesFilter value='parent' checked></input>
          Is <span style="color:green">parent</span> of
        </label>
      </div>
      <div>
        <label>
          <input type='checkbox' #edgesFilter value='teacher' checked></input>
          Is <span style="color:blue">teacher</span> of
        </label>
      </div>
      <div>
        <label>
          <input type='checkbox' #edgesFilter  value='friend' checked></input>
          Is <span style="color:red">friend</span> of
        </label>
      </div>
    </label>
</div>

<div #network>

</div>

ts:


import { Component, AfterViewInit, ElementRef, ViewChild } from '@angular/core';
import { Network, DataSet, DataView} from 'vis';

@Component({
  selector: 'app-test',
  templateUrl: './test.component.html',
  styleUrls: ['./test.component.scss']

})
export class TestComponent implements AfterViewInit {
  @ViewChild('network', {static: false}) el: ElementRef;
  @ViewChild('nodeFilterSelect', {static:false}) nodeFilter: ElementRef;
  @ViewChild('edgesFilter', {static: false}) edgeFilter: ElementRef;
  private networkInstance: any;

  ngAfterViewInit() {

    function startNetwork(data){
      const container = this.el.nativeElement;
      this.networkInstance = new Network(container, data, {});
    }

     const nodes = new DataSet<any>([
        { id: 1, label: 'Eric Cartman', age: 'kid', gender: 'male' },
        { id: 2, label: 'Stan Marsh', age: 'kid', gender: 'male' },
        { id: 3, label: 'Wendy Testaburger', age: 'kid', gender: 'female' },
        { id: 4, label: 'Mr Mackey', age: 'adult', gender: 'male' },
        { id: 5, label: 'Sharon Marsh', age: 'adult', gender: 'female' }
    ]);

    const edges = new DataSet<any>([
        { from: 1, to: 2, relation: 'friend', arrows: 'to, from', color: { color: 'red'} },
        { from: 1, to: 3, relation: 'friend', arrows: 'to, from', color: { color: 'red'} },
        { from: 2, to: 3, relation: 'friend', arrows: 'to, from', color: { color: 'red'} },
        { from: 5, to: 2, relation: 'parent', arrows: 'to', color: { color: 'green'} },
        { from: 4, to: 1, relation: 'teacher', arrows: 'to', color: { color: 'blue'} },
        { from: 4, to: 2, relation: 'teacher', arrows: 'to', color: { color: 'blue'} },
        { from: 4, to: 3, relation: 'teacher', arrows: 'to', color: { color: 'blue'} },
    ], {});

    /**
     * filter values are updated in the outer scope.
     * in order to apply filters to new values, DataView.refresh() should be called
     */
    let nodeFilterValue = ''
    const edgesFilterValues = {
      friend: true,
      teacher: true,
      parent: true
    }

    /*
      filter function should return true or false
      based on whether item in DataView satisfies a given condition.
    */
    const nodesFilter = (node) => {
      if (nodeFilterValue === '') {
        return true
      }
      switch(nodeFilterValue) {
        case('kid'):
          return node.age === 'kid'
        case('adult'):
          return node.age === 'adult'
        case('male'):
          return node.gender === 'male'
        case('female'):
          return node.gender === 'female'
        default:
          return true
      }
    }

    const edgesFilter = (edge) => {
      return edgesFilterValues[edge.relation]
    }

    const nodesView = new DataView(nodes, {filter: nodesFilter})
    const edgesView = new DataView(edges, {filter: nodesFilter})


    this.nodeFilter.nativeElement.addEventListener('change', (e) => {
      // set new value to filter variable
      nodeFilterValue = e.target.value
      /*
        refresh DataView,
        so that its filter function is re-calculated with the new variable
      */
      nodesView.refresh()
    })

    this. edgeFilter.nativeElement.forEach(filter => filter.addEventListener('change', (e) => {
      const { value, checked } = e.target
      edgesFilterValues[value] = checked
      edgesView.refresh()
    }))

    startNetwork({ nodes: nodesView, edges: edgesView })



  }
}

实际上我指的是这段代码,想把它转换成angular格式: https://github.com/visjs/vis-network/blob/master/examples/network/data/dynamicFiltering.html

函数startNetwork(data)在生命周期钩子里面AfterViewInitngAfterViewInit(),这就是为什么