Angular 17 isn't notifying child component of signal changes

In the statistics module, I have a signal that specifies the type of charts to display and this signal is updated through a radio button group. The signal:

typeSignal = signal<string>('OIA')

The radio buttons for setting the :

<div class="btn-group w-auto" role="group">
     @for (type of types; track $index) {
            <input type="radio" class="btn-check" name="btnradio" [id]="type" autocomplete="off"
                [checked]="type==typeSignal()">
            <label class="btn btn-primary" for="btnradio1" (click)="typeSignal.set(type)">{{type}}</label>
     }
</div>

Additionally, there is another computed signal that generates data for the charts based on the type signal. Here's the charts signal:

  charts = computed(() => {
    const chartsArr:ChartData[] = []
   if (this.typeSignal() == "OIA") {

      chartsArr.push(this.createBarChart("Status of Incident", ['Closed', 'Ongoing'], "status", "Advisories", true))
      chartsArr.push(this.createBarChart("Severity of Incident", ['Severity 0', 'Severity 1', 'Severity 2', 'Severity 3', 'Severity 4'], "impacts", "Advisories", false))
      chartsArr.push(this.createDonutChart("Communication type", ['Incident', 'Change'], 300))

    } else if (this.typeSignal() == "Portail de l'information") {

      chartsArr.push(this.createBarChart("Status of Incident", ['Scheduled', 'Archived', 'Ongoing'], "status", "Advisories", true))
      chartsArr.push(this.createBarChart("Impact of Incident", ['Major', 'Minor', 'Grave'], "impacts", "Advisories", false))
      chartsArr.push(this.createDonutChart("Communication type", ['Incident', 'Change'], 300))

    } else if (this.typeSignal() == "Bulletin Board") {
      chartsArr.push(this.createBarChart("Status of Change", ['Closed', 'Ongoing', 'Scheduled'], "status", "Advisories", true))
      chartsArr.push(this.createBarChart("Outage of Incident", ['Complete Outage', 'Partial Outage', 'Info'], "impacts", "Advisories", false))
      chartsArr.push(this.createDonutChart("Communication type", ['Info', 'Incident', 'Change'], 300))
    }
    console.log(chartsArr);
    return structuredClone(chartsArr)
  })

In the template, I'm reading this charts signal as follows:

@if (["OIA","Portail de l'information","Bulletin Board"].includes(typeSignal())) {
<div class="row row-cols-2 g-5 mx-1">
    @for (chart of charts(); track $index) {
    @if (chart.type == "bar") {
    <app-bar-chart [title]="chart.title" [axissLabels]="chart.labels" [values]="chart.values"
        [valuesType]="chart.valuesType!" [isHorizontal]="chart.isHorizontal!"></app-bar-chart>
    }@else if (chart.type=="donut") {
    <app-donut-chart [title]="chart.title" [values]="chart.values" [labels]="chart.labels"
        [minWidth]="chart.minWidth!"></app-donut-chart>
    }
    }

</div>
}

The issue here is that the charts signal does not update the for loop even though the console.log(chartsArr); within it gets logged whenever I toggle the radio buttons.

Answer №1

Upon investigation, it became apparent that the issue did not stem from the signal itself.

The root of the problem lay in the child components BarChartComponent and DonutChartComponent.

These components were failing to detect update changes, prompting the addition of OnChanges.

Below is the revised code for DonutChartComponent:

export type ChartOptions = {
  series: ApexNonAxisChartSeries;
  chart: ApexChart;
  responsive: ApexResponsive[];
  labels: string[];
  title: ApexTitleSubtitle;
};

@Component({
  selector: 'app-donut-chart',
  standalone: true,
  imports: [NgApexchartsModule],
  templateUrl: './donut-chart.component.html',
  styleUrl: './donut-chart.component.scss'
})
export class DonutChartComponent implements OnInit, OnChanges {
  @ViewChild("chart") chart!: ChartComponent;
  chartOptions!: Partial<ChartOptions>;

  @Input() values: number[] = []
  @Input() labels: string[] = []

  @Input() title!: string
  @Input() minWidth!: number


  ngOnInit(): void {
    this.createChart()
  }
  ngOnChanges(changes: SimpleChanges) {
    if (Object.keys(changes).length > 0) {
      if (changes['values']?.currentValue) {
        this.values = changes['values']?.currentValue
      }
      if (changes['labels']?.currentValue) {
        this.labels = changes['labels']?.currentValue
      }
      if (changes['title']?.currentValue) {
        this.title = changes['title']?.currentValue
      }
      if (changes['minWidth']?.currentValue) {
        this.minWidth = changes['minWidth']?.currentValue
      }
      this.createChart()
    }
  }

  createChart() {
    this.chartOptions = {
      title: {
        text: this.title
      },
      series: this.values,
      chart: {
        type: "donut",
      },
      labels: this.labels,
      responsive: [
        {
          breakpoint: this.minWidth,
          options: {
            chart: {
              width: this.minWidth,
            },
            legend: {
              position: "bottom",
            },
          },
        },
      ],
    };
  }

}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Migrating to Angular Universal for server-side rendering with an external API server

Thank you for taking the time to read my query. I have developed a project using server-side Node.js and client-side Angular 6. The purpose of the app is to provide information on cryptocurrency prices and details. I am now looking to transition my Angu ...

The Angular service uses httpClient to fetch CSV data and then passes the data to the component in JSON format

I'm currently working on an Angular project where I am building a service to fetch CSV data from an API server and convert it to JSON before passing it to the component. Although the JSON data is successfully logged in the console by the service, the ...

Merging two arrays that have identical structures

I am working on a new feature that involves extracting blacklist terms from a JSON file using a service. @Injectable() export class BlacklistService { private readonly BLACKLIST_FOLDER = './assets/data/web-blacklist'; private readonly blackl ...

How can the values from the scale [-60, -30, -10, 0, 3, 6, 10] be converted to a decimal range of 0-1 through

Thank you for helping me with so many of my issues. <3 I'm certain that someone has already solved this, but I'm unsure of the specific mathematical term (I've attempted reverse interpolation and others, but with no luck) so I am present ...

How to extract a JavaScript object from an array using a specific field

When dealing with an array of objects, my goal is to choose the object that has the highest value in one of its fields. I understand how to select the value itself: Math.max.apply(Math, list.map(function (o) { return o.DisplayAQI; })) ... but I am unsur ...

Utilizing ngmodel to dynamically populate select dropdowns in Angular version 8

In the form, there are two dropdown menus for selecting start time and end time. The first dropdown menu uses a time array to select a time, and then the index of this selected time is used to create an array for the second dropdown menu. This ensures that ...

Setting a maximum limit for selections in MUI Autocomplete

Code updated to display the complete script logic. I want to restrict the number of selections based on a value retrieved from the database, but in this example, I have set it to 3 manually. The error message I'm encountering is "Cannot read properti ...

Utilizing Angular to enhance tracking page views with the latest Google Analytics integration

I have been using various Angular applications to track page views, implementing a strategy similar to the one outlined in this blog post. In order to avoid third party references, I will provide the relevant code snippets here. To include the gtag depen ...

Unable to locate the next/google/font module in my Typescript project

Issue With Import Syntax for Font Types The documentation here provides an example: import { <font-name> } from 'next/google/font'; This code compiles successfully, but throws a "module not found" error at runtime. However, in this disc ...

Issue: The data type 'void' cannot be assigned to the data type 'ReactNode'

I am encountering an issue while calling the function, this is just for practice so I have kept everything inside App.tsx. The structure of my class is as follows: enum Actor { None = '', } const initializeCard = () => { //some logic here ...

Having Trouble with Angular Route (6) Configuration

I've been experiencing some unusual issues with the Angular 6 router, but this particular one is really frustrating. Here are the routes that I have defined in routing-app.module.ts: export const routes: Routes = [ { path: 'login&a ...

Ionic 2 fails to navigate when using [navPush]

Today I delved into working with Ionic 2 and was making good progress. I had successfully implemented navigation across 3-4 pages, but then something suddenly broke that has left me scratching my head. Now whenever I try to navigate to another page, I kee ...

Creating crawlable AMP versions of Angular websites

Having an Angular website where I dynamically load object properties, I am creating separate AMP sites for each of these objects. Typically, I would link to the AMP site from the canonical site. However, the issue arises because the crawler cannot find the ...

The absence of the google-services.json file has rendered the Google Services Plugin inoperable. Attempted search location:

Having an issue while trying to integrate my app with Firebase. The error message keeps indicating: > File google-services.json is missing. For a more detailed view of the error, please refer to the image below: https://i.stack.imgur.com/sgNYu.jpg D ...

Are MobX Observables interconnected with RxJS ones in any way?

Is the usage of RxJs observables in Angular comparable to that in React and MobX? I'm struggling to find information on this topic. ...

No changes made to Observable when it's empty

I encountered an unusual issue with the rxjs "filter" in my development environment: SAP ComposableStorefront / Spartacus "~2211.21.0" angular 17.2.0 Currently, I am on a product detail page and applying a filter to my Observable in the following manner: ...

Creating personalized mapping for TypeScript objects

I have a TypeScript object structure that resembles the following: { "obj1" : { object: type1;}; "obj2" : { object: type2;}; "obj3" : { object: type3;}; "obj4" : { object: type4;}; "obj5" ...

Error message: Unable to associate with DIRECTIVE as it is not a recognized attribute of 'div'

Despite searching through similar questions about this error, I have not been able to find a solution. The issue arises with my highlight directive, which takes an input parameter index. Initially, the directive worked perfectly when declared within the m ...

"Encountering a Bug in Angular 2 Related to Chart.js

I am currently in the process of developing a Twitter-style application using a Typescript/Angular2 front-end framework and a Node.js back-end. The foundation of my project is derived from Levi Botelho's Angular 2 Projects video tutorial, although I h ...

Guide to Re-rendering a component inside the +layout.svelte

Can you provide guidance on how to update a component in +layout.svelte whenever the userType changes? I would like to toggle between a login and logout state in my navbar, where the state is dependent on currentUserType. I have a store for currentUserTyp ...