Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Showing dynamic data in ng-apexcharts

I want to be able to use the results of this loop: <div *ngFor="let hour of hours | async">{{ hour.messages }}</div> be used in the [series] of an Apex Chart.

For example: <apx-chart *ngFor="let hour of hours | async" class="apex-charts" [series]="{{ hour.messages }}" [chart]="lineChart.chart"></apx-chart>, which obviously does not work.

In a different chart, I was able to successfully use [series]="[{name: 'Messages', data: [message.sunday, message.monday, message.tuesday, message.wednesday, message.thursday, message.friday, message.saturday]}]" when I couched in it a loop of <div *ngFor="let message of messages | async">, but I'm looking to not have to explicitly declare the order.

(While this data will change every day, I don't envision the need for the data to actually be live on the chart.)

like image 304
Ezra Butler Avatar asked Dec 05 '25 21:12

Ezra Butler


1 Answers

I solved my problem in two different ways.

I realized that if I just put an array into the [series] (without brackets), it works perfectly. So in my NodeJS script, I simply created an updated fields called hourlyarray and average on my message document.

I was able to put into a ChartJs Bar Chart canvas:

 <canvas *ngIf="message | async as message; else loading" baseChart 
                        [datasets]="[{ data: message.hourlyarray, label: 'Today' },
                                     { data: message.average, label: 'Average' }]"
                        [labels]="barChartLabels"
                        [options]="barChartOptions"
                        [plugins]="barChartPlugins"
                        [legend]="barChartLegend"
                        [chartType]="barChartType">
                    </canvas>

But I still had a problem that I wanted to include the number of messages during each part of the day, per day, and each day had its own document in a collection called messagedata. On each document (named with the date 2020-01-01, 2020-01-02 ... ), I had broken the day into 5 different parts earlymorning, morning, midday, evening, night.

In my component.ts, I mapped each of these from the messagedata collection.

 this.earlymorningRef = collectionRef.collection('messagedata').valueChanges().pipe(map(data => data.map(d => d.earlymorning)));
 this.morningRef = collectionRef.collection('messagedata').valueChanges().pipe(map(data => data.map(d => d.morning)));
 this.middayRef = collectionRef.collection('messagedata').valueChanges().pipe(map(data => data.map(d => d.midday)));
 this.eveningRef = collectionRef.collection('messagedata').valueChanges().pipe(map(data => data.map(d => d.evening)));
 this.nightRef = collectionRef.collection('messagedata').valueChanges().pipe(map(data => data.map(d => d.night)));
 this.dateRef = collectionRef.collection('messagedata').valueChanges().pipe(map(data => data.map(d => d.date)));

(using map from rxjs/operators)

and then on my component.html, I created an Apex chart.

<h4 class="header-title mt-1">Times of day</h4>

<apx-chart *ngIf="{earlymorning: earlymorningRef | async, 
morning: morningRef | async, 
midday: middayRef | async, 
evening: eveningRef | async, 
night: nightRef | async, 
date: dateRef | async } as messagedataRef; else loading" 
class="apex-charts" 
[series]="[{name: 'Early Morning',data: messagedataRef.earlymorning},
{name: 'Morning',data: messagedataRef.morning},
{name: 'Midday',data: messagedataRef.midday},
{name: 'Evening',data: messagedataRef.evening},
{name: 'Night',data: messagedataRef.night}]" 
[chart]="timeofdayChart.chart" 
[xaxis]="{categories:  messagedataRef.date, axisBorder: {show: true}}" [tooltip]="timeofdayChart.tooltip" [stroke]="timeofdayChart.stroke" [autoUpdateSeries]="false" 
[title]="timeofdayChart.title" [grid]="timeofdayChart.grid" [colors]="timeofdayChart.colors" [responsive]="timeofdayChart.responsive" [dataLabels]="timeofdayChart.dataLabels"></apx-chart>

Using the same method, I was able to create a graph of the daily amount of messages from the past week.

this.pastweekUsageRef = messageRef.collection(('messagedata'), 
ref=> ref.orderBy("date", "desc").limit(8)).valueChanges()
.pipe(map(data => data.map(d => d.usage).slice(0).reverse()));

this.pastweekDateRef = messageRef.collection(('messagedata'), 
ref=> ref.orderBy("date", "desc").limit(8)).valueChanges()
.pipe(map(data => data.map(d => d.date).slice(0).reverse()));

One note: It seems like you cannot use a pipe like | date: 'EE' on the dateRef array.

like image 145
Ezra Butler Avatar answered Dec 07 '25 15:12

Ezra Butler