currently using angular 7 with d3 v7. Trying to render area chart in each cell of table (shown in picture below). But using angular method the rendered svg keeps rendering in a loop. Not sure what im doing wrong here
HTML Code
<tr [id]="'row' '-' fleet" *ngFor="let fleet of fleetcolumn">
<td>{{ fleet }}</td>
<ng-container *ngFor="let station of formattedBaseStations | slice: 1">
<td style="width: 28em;">
<div [id]="'demandChartInTable1-' station '-' fleet '-A'"> {{d3DemandChartIntable(station, fleet, 'A')}} </div>
</mat-grid-tile>
<mat-grid-tile class="FOChart">
<div [id]="'demandChartInTable1-' station '-' fleet '-B'"> {{d3DemandChartIntable(station, fleet, 'A')}} </div>
</mat-grid-tile>
</mat-grid-list>
</td>
</ng-container>
</tr>
.ts code
d3DemandChartIntable(station, code, position) {
// set data
let temp1 = this.data
.filter(d => d.baseCode == station && d.code == code && d.position == position)
.map(d => {
return {
date: d3.timeParse('%Y-%m-%d')(d.date),
hours: d.hours
};
});
const e = document.querySelector('.captainChart');
// set the dimensions and margins of the graph
const margin = { top: 0, right: 0, bottom: 1, left: 1 },
width = 120 - margin.left - margin.right,
height = 90 - margin.top - margin.bottom;
// append the svg object to the body of the page
const svg = d3
.select(`#demandChartInTable1-${station}-${fleet}-${position}`)
.append('svg')
.attr('width', e.clientWidth margin.left margin.right)
.attr('height', e.clientHeight margin.bottom)
.append('g')
.attr('transform', `translate(${margin.left},${margin.top})`);
const x = d3
.scaleTime()
.domain(d3.extent(data, d => d.date))
.range([0, e.clientWidth]);
// Y axis
const y = d3
.scaleLinear()
.domain([0, 500])
.range([e.clientHeight margin.bottom, 0]);
// Add the area
return svg
.append('path')
.datum(temp1)
.attr('fill', '#cce5df')
.attr('stroke', '#69b3a2')
.attr('stroke-width', 1.5)
.attr(
'd',
d3
.area()
.x(d => x(d.date))
.y0(y(0))
.y1(d => y(d.hours))
);
}
Above code renders repeated svg in each cell instead of rendering just once
any help would be greatly appreciated
CodePudding user response:
The crux is in the following code:
const svg = d3
.select(`#demandChartInTable1-${station}-${fleet}-${position}`)
.append('svg')
It selects the table cell and then appends an SVG element. That means that if an SVG already exists, another one is added next to it. If you want to solve this issue, you can either
- Select and update the existing SVG and only create one once (for example in
ngOnInit
orngAfterViewInit
); - Delete any existing SVGs and draw a new one, using
const cell = d3.select(`#demandChartInTable1-${station}-${fleet}-${position}`);
cell.remove('*');
const svg = cell.append('svg')