Paco Zevallos
Paco Zevallos

Reputation: 2285

Angular signal shared data between child components

I have a parent component A and two child components B and C. I'm testing signals with Angular 17. My question is how do I share the value of a signal from component B to component C?

I have tried the following and it works the first time but when the signal value changes it does not update.

componentB.component.ts

 export const item = signal<any>('');

 getFileInformation() {

    this.loading = true;
    
    const functions = getFunctions(getApp());
    connectFunctionsEmulator(functions, 'localhost', 5001);

    const getInfo = httpsCallable(functions, 'getInformation')
    getInfo(this.url.value)
    .then( (result: any) => {
      // result.data return object
      item.set(result.data);
      console.log(item());
    })
  }

componentC.component.ts

import { item } from '../componentB/componentB.component';

item_ = item;

componentC.component.html

<p class="">{{item_().data.title}}</p>

In the console I always get the new updated signal data, but in the HTML template it is not updated. Any ideas?

Upvotes: 2

Views: 3216

Answers (2)

Ashwin Patha
Ashwin Patha

Reputation: 1

You should not use @inputs for signals. Power of signals is cross component communication not just parent-child relation.

You can create a service and share the signal between the components that way it avoids unnecessary updates and cause issues.

Upvotes: 0

Naren Murali
Naren Murali

Reputation: 57696

You can pass it as @Input, working example below!

parent

import { CommonModule } from '@angular/common';
import { Component, signal } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
import 'zone.js';
import { TestComponent } from './test/test.component';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [CommonModule, TestComponent],
  template: `
    <app-test [item]="item"></app-test>
  `,
})
export class App {
  item = signal<any>('');

  ngOnInit() {
    this.getFileInformation();
  }

  getFileInformation() {
    // this.loading = true;

    // const functions = getFunctions(getApp());
    // connectFunctionsEmulator(functions, 'localhost', 5001);

    // const getInfo = httpsCallable(functions, 'getInformation')
    // getInfo(this.url.value)
    // .then( (result: any) => {
    // result.data return object
    // mock the API call!
    this.item.set({ data: { title: 'hello!' } });
    setTimeout(() => {
      this.item.set({ data: { title: 'hello world!' } });
    }, 2000);
    console.log(this.item());
    // })
  }
}

bootstrapApplication(App);

child

import { CommonModule } from '@angular/common';
import { Component, Input, OnInit, Signal } from '@angular/core';

@Component({
  selector: 'app-test',
  imports: [CommonModule],
  template: `
    <p class="">{{ item()?.data?.title | json }}</p>

  `,
  standalone: true,
})
export class TestComponent implements OnInit {
  @Input() item!: Signal<any>;
  constructor() {}

  ngOnInit() {}
}

stackblitz

Upvotes: 0

Related Questions