You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular服务订阅后如何全局赋值并渲染ngx-charts图表

问题:Angular中ngx-charts饼图无法更新数据

在Angular组件中,尝试通过服务获取数据后更新全局变量,进而渲染ngx-charts饼图,但饼图始终无法显示正确数据。具体情况:

  • CandidateService的getCuestionarioRespuestas方法返回Verdaderos类型的Observable数组
  • 组件中定义了全局变量M、N、P并初始化为0,在getRespuestasCandidato方法中订阅服务,计算得到countN2、countM2、countP2后赋值给全局变量,控制台能打印正确数值,但饼图的数据源single数组无法更新
  • 已在AfterViewInit生命周期钩子中调用getRespuestasCandidato方法,但问题依旧

服务代码

import { NumberInput } from '@angular/cdk/coercion';
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { Candidato } from "../interfaces/candidato";
import { Cuestionario } from '../interfaces/cuestionario';
import { Respuesta } from '../interfaces/Respuesta';
import { Verdaderos } from '../interfaces/verdaderos';
@Injectable({
  providedIn: 'root'
})
export class CandidateService {

  url="http://localhost:3000/api"

  constructor(private http:HttpClient) { }

  getPersona(ID:Number):Observable<Candidato[]>{
    return this.http.get<Candidato[]>(this.url + "/persona/searchrh/"+ID)
  }

  deletePersona(ID_RH:Number,ID:Number){
    return this.http.delete<Respuesta>(this.url+"/persona/deleteRH/"+ID_RH+"/"+ID)
  }

  getCandidato(ID:Number):Observable<Candidato>{
    return this.http.get<Candidato>(this.url + "/persona/search/"+ID)
  }

  getCuestionarioRespuestas(ID:Number):Observable<Verdaderos[]>{
    return this.http.get<Verdaderos[]>(this.url + "/cuestionario/"+ID)
  }
}

Verdaderos接口

export interface Verdaderos{
    Pregunta: number;
}

组件方法代码

getRespuestasCandidato(ID: Number) {
    this.Persona.getCuestionarioRespuestas(ID).subscribe((data:Verdaderos[]) =>{
      this.conteo = data;
      this.numbers = this.conteo.map(x => x.ID_Pregunta);
      console.log(this.numbers)

      const N2 = this.N1.filter(x => this.numbers.includes(x));
      const countN2 = N2.length;
      console.log(countN2)

      const M2 = this.M1.filter(x => this.numbers.includes(x));
      const countM2 = M2.length;
      console.log(countM2)

      const P2 = this.P1.filter(x => this.numbers.includes(x));
      const countP2 = P2.length;
      console.log(countM2)
      this.N = countN2;
      this.M = countM2;
      this.P = countP2
    })
  }

饼图数据代码

NE = 100 - this.N- this.M- this.P

single = [
    {
      "name": "Narcisismo",
      "value": this.N    
    },
    {
      "name": "Maquiavelismo",
      "value": this.M
    },
    {
      "name": "Psicopatia",
      "value": this.P
    },
    {
      "name": "No evaluado",
      "value": this.NE
    }
  ];

HTML模板

<div class="wrapperuser">
    <div class="container-sm grafico">
        <ngx-charts-pie-chart
        [view]="view"
        [results]="single"
        [gradient]="gradient"
        [legend]="showLegend"
        [labels]="showLabels"
        [doughnut]="isDoughnut">
        </ngx-charts-pie-chart>
    </div>
</div>

问题原因

  1. single数组初始化时机错误:single数组是在组件类初始化时(构造函数执行前)定义的,此时N、M、P都是初始值0,后续即使这些变量更新,single数组不会自动重新计算。
  2. 未触发变更检测:虽然更新了N、M、P,但没有更新single数组的引用,Angular的变更检测机制无法感知到数据变化,因此饼图不会重新渲染。

解决方案

方案1:数据更新后重新生成single数组

修改getRespuestasCandidato方法,在赋值N、M、P后,重新计算并赋值single数组:

getRespuestasCandidato(ID: Number) {
    this.Persona.getCuestionarioRespuestas(ID).subscribe((data:Verdaderos[]) =>{
      this.conteo = data;
      this.numbers = this.conteo.map(x => x.ID_Pregunta);
      console.log(this.numbers)

      const N2 = this.N1.filter(x => this.numbers.includes(x));
      const countN2 = N2.length;
      console.log(countN2)

      const M2 = this.M1.filter(x => this.numbers.includes(x));
      const countM2 = M2.length;
      console.log(countM2)

      const P2 = this.P1.filter(x => this.numbers.includes(x));
      const countP2 = P2.length;
      console.log(countP2) // 修正原代码笔误:将countM2改为countP2

      this.N = countN2;
      this.M = countM2;
      this.P = countP2;
      
      // 重新生成single数组
      const NE = 100 - this.N - this.M - this.P;
      this.single = [
        { name: "Narcisismo", value: this.N },
        { name: "Maquiavelismo", value: this.M },
        { name: "Psicopatia", value: this.P },
        { name: "No evaluado", value: NE }
      ];
    })
}

同时将组件中原来的NE和single改为类属性:

N = 0;
M = 0;
P = 0;
single: any[] = [];

方案2:使用Getter动态计算single数组

将single定义为Getter属性,每次访问时自动根据最新的N、M、P计算:

N = 0;
M = 0;
P = 0;

get single() {
  const NE = 100 - this.N - this.M - this.P;
  return [
    { name: "Narcisismo", value: this.N },
    { name: "Maquiavelismo", value: this.M },
    { name: "Psicopatia", value: this.P },
    { name: "No evaluado", value: NE }
  ];
}

此时无需提前初始化single数组,Angular会在每次渲染模板时调用Getter获取最新数据。

额外注意点

  • 原代码中console.log(countM2)是笔误,应改为console.log(countP2),需修正。
  • 两种方案都能触发Angular变更检测,让饼图获取到最新数据,可根据实际场景选择。

内容的提问来源于stack exchange,提问作者Alex Ramos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 15:15:38