任何人都知道如何通过单击按钮将过滤器应用于图表吗?假设我已经有了包含尺寸和进行保存搜索的过滤器的对象,现在我想在单击按钮时应用该过滤器。
我正在Angular中进行此操作,我试图创建一个可用于将过滤器应用于所有图表的服务。
这是我到目前为止尝试过的:
我有一个包含所有图表的组件
this.patients = v;
this.ndx = crossfilter(this.patients);
this.cs.samplesGroup = this.ndx.dimension((d) => {
return d.sampleId;
}, true).group();
const all = this.ndx.groupAll();
var genderDim = this.ndx.dimension(function(d){ return d.gender;})
var genderGroup = genderDim.group();
var conditionDim = this.ndx.dimension(function(d){
return d.conditions;
});
var conditionGroup = conditionDim.groupAll().reduce(this.reduceAdd, this.reduceRemove, this.reduceInitial).value();
conditionGroup.all = function() {
var newObject = [];
for (var key in this) {
if (this.hasOwnProperty(key) && key != "all") {
newObject.push({
key: key,
value: this[key],
});
}
}
return newObject;
}
var conditionDim = this.ndx.dimension(function(d){
return d.conditions;
});
var alanineInCerebralSpinalFluidDim = this.ndx.dimension(function(d){ return d.alanineInCerebralSpinalFluid;});
var alanineInCerebralSpinalFluidGroup = alanineInCerebralSpinalFluidDim.group();
var lactateInCerebralSpinalFluidDim = this.ndx.dimension(function(d){ return d.lactateInCerebralSpinalFluid;});
var lactateInCerebralSpinalFluidGroup = lactateInCerebralSpinalFluidDim.group();
var alanineInSerumOrPlasmaDim = this.ndx.dimension(function(d){ return d.alanineInSerumOrPlasma;});
var alanineInSerumOrPlasmaGroup = alanineInSerumOrPlasmaDim.group();
var lactateInVenousBloodDim = this.ndx.dimension(function(d){ return d.lactateInVenousBlood;});
var lactateInVenousBloodGroup = lactateInVenousBloodDim.group();
var choiceDilatedDim = this.ndx.dimension(function(d){ return d.choiceDilated;});
var choiceDilatedGroup = choiceDilatedDim.group();
var choiceHyperthrophicDim = this.ndx.dimension(function(d){ return d.choiceHyperthrophic;});
var choiceHyperthrophicGroup = choiceHyperthrophicDim.group();
var choiceLeftVentricularNonCompactionDim = this.ndx.dimension(function(d){ return d.choiceLeftVentricularNonCompaction;});
var choiceLeftVentricularNonCompactionGroup = choiceLeftVentricularNonCompactionDim.group();
var choiceEndocardialFibroElastosisDim = this.ndx.dimension(function(d){ return d.choiceEndocardialFibroElastosis;});
var choiceEndocardialFibroElastosisGroup = choiceEndocardialFibroElastosisDim.group();
this.charts = [
new MitochondriaChart(
'gender',
'pie',
genderDim,
340,
200,
true,
genderGroup,
),
new MitochondriaChart(
'alanineInCerebralSpinalFluid',
'bar',
alanineInCerebralSpinalFluidDim,
340,
200,
true,
alanineInCerebralSpinalFluidGroup,
null,
'Alanine [Moles/volume] in Cerebral spinal fluid',
'# Samples',
),
new MitochondriaChart(
'lactateInCerebralSpinalFluid',
'bar',
lactateInCerebralSpinalFluidDim,
340,
200,
true,
lactateInCerebralSpinalFluidGroup,
null,
'Lactate [Moles/volume] in Cerebral spinal fluid',
'# Samples',
),
new MitochondriaChart(
'alanineInSerumOrPlasma',
'bar',
alanineInSerumOrPlasmaDim,
340,
200,
false,
alanineInSerumOrPlasmaGroup,
null,
'Alanine [Moles/volume] in Serum or Plasma',
'# Samples',
),
new MitochondriaChart(
'lactateInVenousBlood',
'bar',
lactateInVenousBloodDim,
340,
200,
false,
lactateInVenousBloodGroup,
null,
'Lactate [Moles/volume] in Venous blood',
'# Samples',
),
new MitochondriaChart(
'choiceDilated',
'pie',
choiceDilatedDim,
340,
200,
false,
choiceDilatedGroup,
),
new MitochondriaChart(
'choiceHyperthrophic',
'pie',
choiceHyperthrophicDim,
340,
200,
false,
choiceHyperthrophicGroup,
),
new MitochondriaChart(
'choiceLeftVentricularNonCompaction',
'pie',
choiceLeftVentricularNonCompactionDim,
340,
200,
false,
choiceLeftVentricularNonCompactionGroup,
),
new MitochondriaChart(
'choiceEndocardialFibroElastosis',
'pie',
choiceEndocardialFibroElastosisDim,
340,
200,
false,
choiceEndocardialFibroElastosisGroup,
),
new MitochondriaChart(
'conditions',
'row',
conditionDim,
1050,
800,
true,
conditionGroup,
(dimension, filters) => {
dimension.filter(null);
if (filters.length === 0)
dimension.filter(null);
else
dimension.filterFunction(function (d) {
if (difference(filters, d).length === 0) return true;
return false;
});
return filters;
},
),
];
dc.dataCount('.dc-data-count')
.dimension(this.ndx)
.group(all);
dc.renderAll();
然后我有图表组件本身:
ngAfterViewInit(): void {
if (this.data.type === "row") {
this.initRowChart();
} else if (this.data.type === "pie"){
this.initPie();
}else if (this.data.type === "bar"){
this.initBarChart();
}
this.chart.on("filtered", (c) => {
this.cd.detectChanges();
this.cs.changes.next();
this.ClinicalFilterService.setFilters(this.data.name, this.chart.filters());
});
this.chart.render();
this.cd.detectChanges();
}
initPie() {
this.chart = dc.pieChart(`.chart .${this.data.name}`)
.width(this.data.width)
.height(this.data.height)
.innerRadius(30)
.slicesCap(10)
.dimension(this.data.dim)
.group(this.data.group)
.title(() => this.data.name);
if(this.ClinicalFilterService.filters[this.data.name] !== undefined){
this.ClinicalFilterService.filters[this.data.name].forEach(filter => {
this.chart.filter(filter);
})
}
if (this.data.filterHandler !== null) {
this.chart.filterHandler(this.data.filterHandler);
}
}
initRowChart() {
this.chart = dc.rowChart(`.chart .${this.data.name}`)
.width(this.data.width)
.height(this.data.height)
.group(this.data.group)
.elasticX(true)
.ordering(function(d){
let i = 0;
if(CONDITION_GROUPING[0].includes(d.key))
return i++;
else if(CONDITION_GROUPING[1].includes(d.key))
return 25 + i++;
else if(CONDITION_GROUPING[2].includes(d.key))
return 50 + i++;
else if(CONDITION_GROUPING[3].includes(d.key))
return 100 + i++;
})
.dimension(this.data.dim)
.colors(d3.scale.ordinal().domain(["a","b","c","d"])
.range(["#d6e8f5","#85bae0", "#348ccb", "#25628e"]))
.colorAccessor(function(d) {
if(CONDITION_GROUPING[0].includes(d.key))
return "a";
else if(CONDITION_GROUPING[1]. includes(d.key))
return "b";
else if(CONDITION_GROUPING[2]. includes(d.key))
return "c";
else if(CONDITION_GROUPING[3]. includes(d.key))
return "d";
});
if(this.ClinicalFilterService.filters[this.data.name]){
this.ClinicalFilterService.filters[this.data.name].forEach(filter => {
this.chart.filter(filter);
})
}
if (this.data.filterHandler !== null) {
this.chart.filterHandler(this.data.filterHandler);
}
}
initBarChart() {
this.chart = dc.barChart(`.chart .${this.data.name}`)
.width(this.data.width)
.height(this.data.height)
.x(d3.scale.linear().domain([0, 100]))
.elasticY(true)
.yAxisLabel(this.data.yAxisLabel)
.xAxisLabel(this.data.xAxisLabel)
.dimension(this.data.dim)
.group(this.data.group);
this.chart.yAxis().ticks(3);
if(this.ClinicalFilterService.filters[this.data.name]){
this.ClinicalFilterService.filters[this.data.name].forEach(filter => {
this.chart.filter(filter);
})
}
if (this.data.filterHandler !== null) {
this.chart.filterHandler(this.data.filterHandler);
}
}
现在,我尝试提供一种将容纳过滤器对象的服务,并且在更改它后,我希望将其应用于所拥有的图表。
private filtersSource = new BehaviorSubject<any>({});
filters = this.filtersSource.asObservable();
chart: crossfilter.baseMixin;
private savedSearchesSource = new BehaviorSubject<any>({});
savedSearches = this.savedSearchesSource.asObservable();
setFilters(name, filter){
let currentFilter = this.filtersSource.getValue();
let newFilter = Object.assign({}, currentFilter, {[name]: filter});
if(newFilter[name].length === 0){
delete newFilter[name];
}
this.filtersSource.next(newFilter);
}
deleteFilter(name){
let currentFilter = this.filtersSource.getValue();
let newFilter = Object.assign({}, currentFilter);
delete newFilter[name];
this.filtersSource.next(newFilter);
}
clearFilters(){
this.filtersSource.next({});
}
saveSearches(name){
let currentSavedSearches = Object.assign({}, this.savedSearchesSource.getValue());
let currentFilter = Object.assign({}, this.filtersSource.getValue());
currentSavedSearches[name] = currentFilter;
this.savedSearchesSource.next(currentSavedSearches);
}
applySavedSearches(savedFilterName) {
let savedSearches = Object.assign({}, this.savedSearchesSource.getValue()[savedFilterName]);
this.filtersSource.next(savedSearches);
}
ngOnDestroy() {
this.filtersSource.next({})
}
我不知道如何将服务上的过滤器应用于我所拥有的图表组件
答案 0 :(得分:0)
您没有说应用过滤器时遇到什么问题,但是这段代码看起来有问题:
if(this.ClinicalFilterService.filters[this.data.name]){
this.ClinicalFilterService.filters[this.data.name].forEach(filter => {
this.chart.filter(filter);
})
}
这可能有用,因为chart.filter(value)
会在过滤器集中切换该值。但是,如此多次更改过滤器可能没有效率。
syntax for applying multiple filters有点奇怪:
chart.filter([[value,value,value]]);
是,一个包含单个包含值的数组的数组。不要问为什么。
实际上,这将切换每个值,就像您单击每个值一样。因此,replaceFilter
可能就是您想要的:
chart.replaceFilter([[value,value,value]]);
那你只需要打电话
chart.redrawGroup();
将过滤器更改应用于组中的所有图表。