2016-10-24 3 views
1

Ich versuche, ein Dashboard für Diagramme mit angular 2 und chart.js (über ngcharts) zu erstellen. Ich hätte gerne eine Reihe von Diagrammen, die jeweils über eine HTTP-Anfrage in einem benutzerdefinierten Intervall aktualisiert werden.Wie aktualisiert man ein Array von Observablen mit Intervall?

Im Moment habe ich drei separate Diagrammaufrufe, die Daten an ein Array senden. Ich habe Probleme, wenn es um die nächste Iteration geht - wenn ich erneut zum Array gehe, werde ich mit 3 weiteren Charts enden. Ich möchte, dass die Abonnenten im Array mit neuen Daten aktualisiert werden, wenn das Intervall sie ausgibt.

Ich bin ein wenig verwirrt, wie die Komponente/Service/http-Beziehung für meinen Anwendungsfall richtig zu strukturieren. Ich fühle, dass ich nah bin, aber ich vermisse definitiv etwas. Wie kann ich die Intervall-/Abonnentenbeziehung auf die Ansicht mappen und die vorhandenen Diagramme in einem Intervall aktualisieren? Jede Hilfe wäre großartig!

Gerade jetzt:

Service:

Ich bin der Umsetzung des Intervalls hier:

getSingleChartObsinterval(id: number, interval: number) : Observable<Graph> { 

return Observable.interval(interval).flatMap(() => this.getSingleChartobs(id));   
} 


getSingleChartobs(id: number) : Observable<Graph> { 

    return this.jsonp.get(“api location”) 
      .map(response => this.extractJsonData(response, id) as Graph) 
} 

extractJsonData ist nur die Antwort zu nehmen und zu manipulieren sie mit dem Diagramm JS zu arbeiten. Sie gibt ein Graph-Objekt mit Eigenschaften zurück, mit denen Sie einfach arbeiten können. Ich habe keine Kontrolle über die API, daher kann ich die Antwort nicht so konfigurieren, dass sie mehr als einen Graphen enthält.

Die Komponente:

import { Component } from '@angular/core'; 
import { ChartsModule } from 'ng2-charts/ng2-charts'; 
import { ChartService } from './chart.service'; 
import { Graph } from './graph'; 
import { OnInit } from '@angular/core'; 
import { Observable } from 'rxjs/Rx'; 


@Component({ 
    selector: 'ab-chart', 
    styles: [` 
    .chart { 
     display: block; 
    } 
    `], 
    templateUrl: 'app/chart.component.html' 
}) 
export class ChartComponent implements OnInit { 

    ngOnInit(): void { 
     console.log("Chart component init"); 

     this.getSingleChart(3, 5000); 
     this.getSingleChart(5, 4000); 
     this.getSingleChart(6, 5000); 
    } 

    graph: Graph; 
    graphs: Graph[] = []; 


    constructor(
     private chartService: ChartService 
    ) {} 


    getSingleChart(id: number, interval: number): void { 
    this.chartService.getSingleChartObsinterval(id, interval) 
     .subscribe(x => 
     this.graphs.push(x) 
    ); 
} 
} 

Aussicht:

<div *ngFor="let graph of graphs" class="chart-container"> 
    <base-chart 
     class="chart" 
     [datasets]="graph.datasets" 
     [labels]="graph.labels" 
     [options]="graph.options" 
     [chartType]="graph.type"> 
     </base-chart> 
    </div> 
+0

statt drängen neue Graph in Ihrem Array, können Sie nicht einfach die vorhandenen Graphen durch neue Daten ersetzen? Ich weiß nichts über chart.js, also ist es vielleicht nicht möglich, seine Daten zu ersetzen und warten Sie einfach auf Winkel, um das neue Diagramm zu rendern –

+0

@ NoémiSalaün Ich denke, das ist eine Art von dem, was ich frage.Jede Tabelle hat ein anderes Intervall, also hoffe ich, dass ich jedes Item haben kann n Das Array abonniert Änderungen und aktualisiert sich selbst, ohne das Array wegblasen zu müssen. Ich habe versucht, jedes Objekt als Abonnent auf das Array zu schieben, aber es hat nicht funktioniert. Ich hoffe, dass es einen Weg gibt, dies zu tun, ohne das Array nach der ID durchsuchen zu müssen und die Daten selbst zu aktualisieren. – Skerrvy

Antwort

1

Da jeder Graph hat seine eigene id (ich nehme an seiner einzigartigen), so würde ich nur getSingleChart() Methode ändern Update graphs Objekt bei bestimmten Schlüssel.Hinweis änderte ich die graphs Eigenschaft von einem Array zu einem Objekt:

graphs: {[key: number]: Graph} = {}; 

getSingleChart(id: number, interval: number): void { 
    this.chartService.getSingleChartObsinterval(id, interval) 
    .subscribe(x => this.graphs[id] = x); 
} 

get graphIds() { 
    return Object.keys(this.graphs); 
} 

dann in der Vorlage müssen Sie die Anordnung von Tasten iterieren (können Sie das graphs Objekt iterieren:

<div *ngFor="let id of graphIds" class="chart-container"> 
    <base-chart 
     class="chart" 
     [datasets]="graphs[id].datasets" 
     [labels]="graphs[id].labels" 
     [options]="graphs[id].options" 
     [chartType]="graphs[id].type"> 
    </base-chart> 
</div> 
+0

Danke für diese Antwort. Beide Antworten funktionierten, aber das ist näher an dem, was ich versucht habe und verursachte die geringste Änderung meines bestehenden Ansatzes. – Skerrvy

1

Haben Sie eine begrenzte Anzahl von Charts? Wenn Sie immer drei haben, können Sie den Operator combineLatest nutzen (wenn Sie mehr haben, müssten Sie eine Form der Rekursion verwenden, denke ich).

In Ihrer Komponente können Sie Folgendes tun:

this.graphs = this.getSingleChart(3, 5000).combineLatest(
     this.getSingleChart(5, 4000), 
     this.getSingleChart(6, 5000), 
     (val1, val2, val3) => return [val1, val2, val3]) 
     //.subscribe((arrayOfVal) => console.log(arrayOfVal); 

Dies wird jedes Mal, wenn einer der Charts ein neues Array zurück aktualisiert wird. Wenn Chart 2 einen neuen Wert erhält, wird die Funktion (drittes Argument des combinateLatest) mit dem alten Wert 1, dem neuen Wert für 2 und dem alten Wert drei aufgerufen.

in Ihrer Vorlage können Sie nur diese verwenden werden:

<div *ngFor="let graph of graphs | async" ...> 

CombineLatest: https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/combinelatest.md

+0

Eigentlich funktioniert das nicht so, weil 'combineLatest()' ein Observable zurückgibt, nicht die Werte, die vom Callback zurückgegeben werden. Dies würde auch bedeuten, dass Sie immer alle Diagramme auf einmal aktualisieren müssen. – martin

+0

Es wird tatsächlich eine beobachtbare zurückgeben. Aber das ist der Punkt, das Observable könnte in diesem Fall mit der asynchronen Pipe in der Vorlage verwendet werden. Und combineLatest erzwingt nicht jedes neu zu aktualisierende Diagramm. Unter den Deckungen wird dies den neuesten Wert aller drei Anrufe enthalten. Zum Beispiel A1, B1 und C1. Wenn B1 auf B2 aktualisiert wird, ist der nächste Wert A1, B2, C1. Beachten Sie, dass A- und C-Referenzen sich NICHT geändert haben. Also, es macht dasselbe wie deine Antwort. Aber eleganter AFAIAC, da Sie das Abonnement danach nicht aufräumen müssen. – KwintenP

+0

Sie haben Recht mit dem 'Async', das habe ich nicht bemerkt. Allerdings muss es alle Diagramme auf einmal aktualisieren und nicht so, wie Sie es beschreiben, weil bei jeder Änderung 'Graphen | async "empfängt ein neues Array und zerstört und erstellt dann alle drei' 's Elemente erneut. Aber deine Lösung ist definitiv einfacher als meine. – martin

Verwandte Themen