The alteration in the child's signal does not result in any impact on the parent

Within the child component, there is a field called data that I modify upon clicking. Following this change, I want an effect to be triggered in the parent component to detect this alteration. Strangely, the effect does not activate when I update the model input in the child (although it works fine when adjusting the signal in the parent).

The code snippet for the child component looks like this:

export class ChildComponent {
  data = model({} as Vm);
  onClick() {
    console.log("Click alters the data.");
    // this.data.set(this.data());
    this.data.update(a => a);
  }
}

And here's the code for the parent component:

export class ParentComponent {

  constructor() {
    interval(1000).subscribe(a => console.log("poll: ", this.data()));
    effect(() => { console.log("effect: ", this.data()) });
  }
  data = signal({} as Vm);
  ngOnInit() { this.data.set(this.getData()); }
}

Initially, I observe an empty object displayed by the effect. Then, I witness the update from the parent’s initialization method. Additionally, I can see the value changed in the child being checked every second. However, the effect fails to trigger again, happening only twice as mentioned earlier.

I'm running out of ideas on how to troubleshoot this issue further. Checking the official documentation, it appears that it should work (and to some extent, it does!). Yet, I'm unsure if I am correctly implementing the modification within the child component.

(In the actual scenario, my goal is to only alter a field within an object contained in the array of the data model input. But before proceeding, I need to understand why neither set(...) nor update(...) activates the effect in the parent.)

Answer №1

When it comes to signal fires, they only happen when the actual value changes. This is because arrays and objects are stored as references in memory. So, if you modify internal properties without changing the memory reference, the change won't be detected. The same goes for simply returning the object as is.

Check out more on Signals And Array Mutability In Angular 18 by Ben Nadel

For Github issue related to mutable signals support in Angular 17, click here

To ensure a change is picked up by the signal, use object destructuring (for objects) or .slice() array method (only for arrays) to create a new memory reference that will propagate to the parent component.


This explanation specifically pertains to effect and computed functionalities in Angular, as they react solely to signal changes.

It's worth noting that observable updates may reflect inner properties of a signal containing an object, but this is not due to signals supporting mutable objects. Instead, it occurs as a side effect of change detection cycles running during things like click events triggering cdr.detectChanges().


@Component({
  selector: 'app-child',
  standalone: true,
  template: `
    <button (click)="onClick()">click</button>
  `,
})
export class ChildComponent {
  data = model({});
  onClick() {
    console.log('Click alters the data.');
    // this.data.set(this.data());
    // object destructuring creates new memory reference.
    this.data.update((a: any) => ({ ...a }));
  }
}

Full Code:

import { Component, effect, model, signal } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
import { interval } from 'rxjs';
@Component({
  selector: 'app-child',
  standalone: true,
  template: `
        <button (click)="onClick()">click</button>
      `,
})
export class ChildComponent {
  data = model({});
  onClick() {
    console.log('Click alters the data.');
    // this.data.set(this.data());
    this.data.update((a: any) => ({ ...a }));
  }
}

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [ChildComponent],
  template: `
    <app-child [(data)]="data" (dataChange)="dataChange($event)"/>
  `,
})
export class App {
  data = signal({});
  constructor() {
    // interval(1000).subscribe((a: any) => console.log('poll: ', this.data()));
    effect(() => {
      console.log('effect: ', this.data());
    });
  }
  ngOnInit() {
    // this.data.set(this.getData());
  }

  dataChange(e: any) {
    console.log(e);
  }
}

bootstrapApplication(App);

View the Stackblitz Demo here

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

The unexplainable phenomenon of variables mysteriously transforming into undefined as they pass

Check out these key sections of my code. Pay attention to the console.log statements. async function matchChannel( context: coda.ExecutionContext, channelLabel: string ) { ... console.log(`allTeamIds = ${JSON.stringify(allTeamIds)}`); try { ...

Saving a datetime in Angular2+ C# Web Api on the server side with incorrect timezone offset

I'm encountering an issue with saving datetime data in my application. The problem arises when the webapi receives the date and converts it to an incorrect time zone. When my Angular app sends the date: Wed May 22 2019 11:03:35 GMT+0200, the Web Api ...

Steps for developing a versatile function Component

Can I create generic function components? I thought that the following example would work: type MyComponentProps<T> = T & { component: ComponentType<T>, primary?: boolean, size?: 'S' | 'M' | 'L' ...

Creating a custom component in Angular 2 that includes several input fields is a valuable skill to have

I have successfully created a custom component in Angular 2 by implementing the CustomValueAccessor interface. This component, such as the Postcode component, consists of just one input field. <postcode label="Post Code" cssClass="form-control" formCon ...

Instructions for configuring the npm root path to ".../Appdata/roaming/npm" are as follows:

I have successfully installed nodejs version 8.12.0 and npm version 6.4.1. Now I am attempting to install angular 1.7.4. I have configured the environment variable path as follows: C:\Users\user_name\AppData\Roaming\npm ...

Does Angular perform tree shaking on a service that is provided at the root level, as long as it is not explicitly injected into a component instance?

Suppose we implement a service similar to this as part of a library: @Injectable({ providedIn: 'root' }) export class ChartJSProvider { constructor() { Chart.register(...registerables); } } and our application makes use of the aforem ...

What is the best way to utilize Quokka when working with TypeScript files that have been imported?

After installing ts-node using NPM, I've spent countless hours trying to get it to work. Unfortunately, I couldn't find any helpful documentation on the website or through a Google search. I have installed ts-node both globally and in my project ...

Error in Typescript/React: Unable to access the property 'MaxEmailLength' as it is undefined

I am facing an unusual problem with TypeScript. I have two static classes that are mutually referencing each other and causing issues. Class ValidationHelper (single file) import { ValidationErrors } from '../dictionary/ValidationErrors'; ex ...

Issue with RouterLink and dynamic parameters (potential load timing problem?)

I am currently working on an IONIC-4 / Angular 7 project and have encountered an issue with the routerLink as shown below; <p>{{ data?.name }}</p> <ion-button [routerLink]="['/', 'tabs', 'projects', data?.name] ...

Guide to adding Angular 5 to Django static directory while enabling hashing functionality

My Django app utilizes an Angular 5 frontend connected by Django REST for deployment. Currently, the deployment process only functions with hashing disabled (--output-hashing none) due to restrictions in urls.py where I can solely access a copy of index.ht ...

Utilizing PrimeNG checkbox groups in a reactive form: A guide to retrieving all selected values

I am facing an issue with a group of <p-checkbox> elements from PrimeNG. They all have the same name and formControlName attributes. The form control's value is an array, but it seems to only retain the selection of the last checkbox clicked. T ...

Make sure to load Meteor.user() prior to initializing Angular 2

I am encountering an issue while setting up a new Meteor - Angular2 application where I am struggling to verify the logged-in user within my router. Below is my current auth-guard.service.ts content featuring an AdminAuthGuard that utilizes implements Can ...

How can I effectively test static navigationOptions using Jest and Enzyme in a React Navigation and TypeScript environment?

Currently, I am developing a React Native app using TypeScript. For component testing, I rely on Jest and Enzyme. Additionally, I have integrated React Navigation into my project. On one of the screens, the navigationOptions are as follows: static naviga ...

Starting up various modules in Angular 6 using arrays

Can an array be declared and used to bootstrap multiple components in module.ts? I attempted the following: export var initialComponents = []; initialComponents.push(AppComponent); if(condition) { initialComponents.push(IchFooterComponen ...

Retrieve the previous route in Angular 7

I have developed a unique service that allows me to store route changes efficiently. import { Injectable } from '@angular/core'; import { Router, NavigationEnd } from '@angular/router'; @Injectable() export class RouteState { priva ...

Generating tables with ngFor in Angular 2

Is it possible to generate a table in Angular 2 with a dynamic number of columns by utilizing a loop based on the specified number? Specifically, how can we create a table without a fixed number of columns? ...

The command "create-nx-workspace" was not found on the Linxus and Windows 10 systems, causing an issue

Could someone please guide me on how to set up nrwl/schematics? I'm currently following a course on frontendmasters that uses nrwl for workspace generation. However, when I try to run the command create-nx-workspace on my Windows and Linux machines, i ...

Leverage the useRef hook with React Draggable functionality

Having recently delved into coding, I find myself navigating the world of Typescript and React for the first time. My current challenge involves creating a draggable modal in React that adjusts its boundaries upon window resize to ensure it always stays wi ...

Inform the PHP backend that the browser has been closed by the frontend Angular application

Currently, I am working on an Angular project that is interacting with a backend project created using PHP and ZF3. I am trying to figure out the most efficient method of informing the backend project when the user closes the browser window. Initially, I ...

To close the Muix DateTimePicker, simply hit the Escape key or click anywhere outside of the picker

I'd like the DateTimePicker to only close when the user presses the action buttons, not when they click outside or press Escape. Unfortunately, I haven't found any props to control this behavior yet. <DesktopDatePicker closeOnSelect={false} s ...