How to I keep two signals in sync (Service and Component)

Discussão em 'Angular' iniciado por Naren Murali, Fevereiro 7, 2025.

  1. Naren Murali

    Naren Murali Guest

    I have this component, which is accepting a parameter as input.required ( say ID ).

    I use this component in multiple places, with different IDs, I want to make sure the current input signal value get's updated on the service so that my resource always fetches the proper data.

    I know I can achieve this by just directly assigning the service signal, but as mentioned earlier, I have multiple inputs, the component must have an id provided (input.required), but my resource lies at the service level (Shared by this component and it's children).

    Above are the requirements of my scenario, below if my minimal reproducible code:

    Service:


    @Injectable({
    providedIn: 'root',
    })
    export class SomeService {
    http = inject(HttpClient);
    serviceIdSignal: WritableSignal<number> = signal(0); // <- I want to sync this at the component level.

    rxResource = rxResource({
    request: () => this.serviceIdSignal(),
    loader: ({ request: id }) => {
    return this.http.get(`https://jsonplaceholder.typicode.com/todos/${id}`);
    },
    });

    resource = resource({
    request: () => this.serviceIdSignal(),
    loader: ({ request: id, abortSignal }) => {
    return fetch(`https://jsonplaceholder.typicode.com/todos/${id}`, {
    signal: abortSignal,
    }).then((r) => r.json());
    },
    });
    }

    Child Component:


    @Component({
    selector: 'app-child',
    template: `
    <div></div>
    `,
    })
    export class Child {
    someService = inject(SomeService);
    componentIdSignal: InputSignal<number> = input.required({
    alias: 'id',
    });
    }

    Root Component:


    @Component({
    selector: 'app-root',
    imports: [Child, JsonPipe],
    template: `
    <app-child [id]="id()"/>
    <hr/>
    {{id()}}
    <hr/>
    @if(someService.rxResource.status() === rs.Resolved) {
    {{someService.rxResource.value() | json}}
    } @else {
    Loading...
    }
    <hr/>
    @if(someService.rxResource.status() === rs.Resolved) {
    {{someService.resource.value() | json}}
    } @else {
    Loading...
    }
    `,
    })
    export class App {
    rs = ResourceStatus;
    someService = inject(SomeService);
    id = signal(1);
    }

    Stackblitz Demo

    Continue reading...

Compartilhe esta Página