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;
startNetwork(data){
const container = this.el.nativeElement;
this.networkInstance = new Network(container, data, {});
}
ngAfterViewInit() {
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()
})
const selectors = this.edgeFilter.nativeElement.querySelectorAll('label')
console.log(selectors)
selectors.forEach(filter => filter.addEventListener('change', (e) => {
const { value, checked } = e.target
edgesFilterValues[value] = checked
edgesView.refresh()
}))
this.startNetwork({ nodes: nodesView, edges: edgesView })
}
}
对于以上代码,我遇到一个错误,提示edgesData.forEach不是Angular中的函数。我认为此错误来自以下代码段:
const selectors = this.edgeFilter.nativeElement.querySelectorAll('label')
console.log(selectors)
selectors.forEach(filter => filter.addEventListener('change', (e) => {
const { value, checked } = e.target
edgesFilterValues[value] = checked
edgesView.refresh()
}))
实际上,我要做的是将事件侦听器添加到我的三个输入值中。像这样的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 #edgesFilter>
Filter edges
<div>
<label>
<input type='checkbox' value='parent' checked>
Is <span style="color:green">parent</span> of
</label>
</div>
<div>
<label>
<input type='checkbox' value='teacher' checked>
Is <span style="color:blue">teacher</span> of
</label>
</div>
<div>
<label>
<input type='checkbox' value='friend' checked>
Is <span style="color:red">friend</span> of
</label>
</div>
</label>
</div>
<div #network>
</div>
这里发生了什么,任何人都可以解释一下吗?我认为我以错误的方式使用了“ foreach”,我在Google上搜索了很多,但仍然对如何循环和添加侦听器感到困惑。
而且我也尝试使用for循环而不是foreach:
const selectors = this.edgeFilter.nativeElement.querySelectorAll('input')
for(const selector of selectors){
console.log(selector)
selector.forEach(filter => filter.addEventListener('change', (e) => {
const { value, checked } = e.target
edgesFilterValues[value] = checked
edgesView.refresh()
}))
}
仍然出现错误说:
ERROR TypeError: selector.forEach is not a function
at TestComponent.ngAfterViewInit (main.js:294)
at callProviderLifecycles (vendor.js:64080)
at callElementProvidersLifecycles (vendor.js:64045)
at callLifecycleHooksChildrenFirst (vendor.js:64027)
at checkAndUpdateView (vendor.js:74910)
at callViewAction (vendor.js:75266)
at execComponentViewsAction (vendor.js:75194)
at checkAndUpdateView (vendor.js:74907)
at callWithDebugContext (vendor.js:76241)
at Object.debugCheckAndUpdateView [as checkAndUpdateView] (vendor.js:75823)
我只是意识到这是visjs的问题,我需要安装@ type / vis
您实际上是将事件添加到label
元素,这将无法正常工作。更改事件适用于input
,select
或textarea
。
我会说这对我来说似乎不是Angular的方式,但是也许我没有看到整个图片。我会做这样的事情,它只是控件和事件的一部分,
import { Component } from '@angular/core';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
filterNodes = '';
selectChange () {
console.log(`filterNodes: ${this.filterNodes}`);
}
chkChange(evt) {
const { value, checked } = evt.target;
console.log(`${value}: ${checked}`);
}
}
<div>
<label>
Filter nodes
<select [(ngModel)]="filterNodes"
(change)="selectChange()">
<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' value='parent' checked
(change)="chkChange($event)">
Is <span style="color:green">parent</span> of
</label>
</div>
<div>
<label>
<input type='checkbox' value='teacher' checked
(change)="chkChange($event)">
Is <span style="color:blue">teacher</span> of
</label>
</div>
<div>
<label>
<input type='checkbox' value='friend' checked
(change)="chkChange($event)">
Is <span style="color:red">friend</span> of
</label>
</div>
</label>
</div>