angularsignalsangular-signalsangular-rxjs-interoprxresource

Angular - react to changes in rxResource()


How one can react to changes / perform side-effects when rxResource receives .value() instead of using effect()?

Current approach in component:

  constructor() {
    this.service.setItemId(1); //setting signal
    effect(() => // work with data from async post request 
  } 

in service:

 resource$ = rxResource({
    request: () => this.itemID$(), // signal 
    loader: ({ request: id }) => {
      return this.http.post('http://');
    }
  }); 

Solution

  • UPDATE:

    As per the requirements, it looks like you want to react to the creation of a new item in the database, but fetching the elements from the database reactively.

    In the below code, we trigger the post on change of itemID$ value, I have used a modal here, this updates the database (PUT) and then we need to read the data to see if it is updated.

    updatePost: ResourceRef<any> = rxResource({
      request: () => this.itemID$(), // signal
      loader: ({ request: id }) => {
        console.log(id);
        return this.http.put(`http://localhost:3000/posts/1`, {
          id: 1,
          title: `from resource - ${id}`,
          views: id * 200,
          userId: 1,
        });
      },
    });
    

    All you need to do is pass the this.updatePost.value() signal execution as a input to the request method, this will trigger the GET api call (getPosts resource), on each post request from the rxResource (updatePost)

    getPosts: ResourceRef<any> = rxResource({
      request: () => this.updatePost.value(), // signal
      loader: (params: ResourceLoaderParams<any>) => {
        console.log(params.request);
        return this.http.get(`http://localhost:3000/posts`);
      },
    });
    

    In the below stackblitz, we update a row in the database, then we get the rows, we can see that the row has been updated.

    1. Open new terminal in stackblitz and run npx json-server db.json.

    2. Then restart the angular server and click on localhost:4200 in the terminal to view the app in the preview and try out the feature.

    Stackblitz Demo



    If you want to derive state from the original signal, then you can use computed, linkedSignal to do this.

    But since you are doing DOM manipulations based on an API call, the best option is to use effect to do this, else you can try to achieve the same result without any DOM manipulations.

    constructor() {
      effect(() => {
        // .. DOM manuipulations.
      })
    }
    

    Ideally you should be able to achieve the same result without DOM manipulations based on signal reactivity, but those details need to be provided for a clear answer.