In v19, Angular will introduce a new API for loading resources. This would allow us to fetch data from an api, know about the status of the request, and update the data locally when needed.

### Intro

The resource API is very simple in it's core. Let's see the most simple example of how to use it.

```
import { resource } from "@angular/core";

@Component({})
export class MyComponent {
  todoResource = resource({
    loader: () =&gt; {
      return Promise.resolve({ id: 1, title: "Hello World", completed: false });
    },
  });

  constructor() {
    effect(() =&gt; {
        console.log("Value: ", this.todoResource.value());
        console.log("Status: ", this.todoResource.status());
        console.log("Error: ", this.todoResource.error());
    })
  }
}
```

The first thing we can notice is that the resource API uses Promises by default for the loader parameter. The other one is that the resource API will return a `WritableResource` object, which helps us to update the data locally when needed.

We can read the current value of the resource by using the `value` signal, the status of the resource by using the `status` signal, and the error of the resource by using the `error` signal.

The code above will print the following:

```
Value: undefined
Status: 'loading'
Error: undefined

Value: { id: 1, title: "Hello World", completed: false }
Status: 'resolved'
Error: undefined
```

### Updating the data locally

Let's see how we can update the data locally.

```
import { resource } from "@angular/core";

@Component({
    template: `
        <button (click)="updateTodo()">Update</button>
    `
})
export class MyComponent {
  todoResource = resource({
    loader: () =&gt; {
      return Promise.resolve({ id: 1, title: "Hello World", completed: false });
    },
  });

  updateTodo() {
    this.todoResource.value.update((value) =&gt; {
      if (!value) return undefined;
      
      return { ...value, title: "updated" };
    });
  }
}
```

We can update the data locally by using the `update` method of the `value` signal.

This will print the following:

```
Value: { id: 1, title: "updated", completed: false }
Status: 'local'
Error: undefined
```

The 'local' status means that the data was updated locally.

### Loading the data

Let's make a proper request to the server. Let's load some todos from the [JSONPlaceholder API](https://jsonplaceholder.typicode.com/).

```
interface Todo {
  id: number;
  title: string;
  completed: boolean;
}

@Component()
export class MyComponent {
  todosResource = resource({
    loader: () =&gt; {
      return fetch(`https://jsonplaceholder.typicode.com/todos?_limit=10`)
        .then((res) =&gt; res.json() as Promise<todo[]>);
    },
  });
}</todo[]>
```

This `todosResource` will start to make the request to the server immediately after it has been created.

Of course, the `todosResource` will not have a value yet, because the request is still in progress.

The code above will print the following:

```
Value: undefined
Status: 'loading'
Error: undefined

Value: [{ id: 1, title: "Hello World", completed: false }, { id: 2, title: "Hello World", completed: false }, ...]
Status: 'resolved'
Error: undefined
```

### Refreshing the data

Let's say we want to refresh the data when the user clicks on a button.

```
import { resource } from "@angular/core";

@Component()
export class MyComponent {
  todosResource = resource({
    loader: () =&gt; {
      return fetch(`https://jsonplaceholder.typicode.com/todos?_limit=10`)
        .then((res) =&gt; res.json() as Promise<todo[]>);
    },
  });

  refresh() {
    this.todosResource.refresh();
  }
}</todo[]>
```

The `refresh` function will run the loader function again. If you call the `refresh` function multiple times, the loader function will be called only once until the previous request is finished (like exhaustMap behavior in RxJS).

### Loading specific date based on other signals

Let's say we want to load the todos based on a `todoId` signal.

```
import { resource } from "@angular/core";

@Component()
export class MyComponent {
  todoId = signal(1);

  todoResource = resource({
    loader: () =&gt; {
      return fetch(
        `https://jsonplaceholder.typicode.com/todos/${this.todoId()}`
      ).then((res) =&gt; res.json() as Promise<todo>);
    },
  });
}</todo>
```

This will work fine, but one this to notice is that `loader` is `untracked` and that means, that if the `todoId` signal changes, the load won't be called again. Let's make it more reactive!

### Separate the request and the loader

We want our resource to refresh the data (call the loader again) every time the `todoId` changes. For this we can use the `request` field of the resource. We can pass a signal to it, and it will be tracked.

```
todoResource = resource({
    request: this.todoId, 
    loader: ({ request: todoId }) =&gt; {  
        return fetch( 
          `https://jsonplaceholder.typicode.com/todos/${todoId}`,
        ).then((res) =&gt; res.json() as Promise<todo>);
    },
});</todo>
```

Now, when the `todoId` signal changes, the resource API will automatically fetch the new data.

What if we have previous unfinished requests? Let's say we want to cancel the previous request when the `todoId` changes. Well, we can do that by using the `abortSignal` that is passed to the loader function.

```
todoResource = resource({
    request: this.todoId, 
    loader: ({ request: todoId, abortSignal }) =&gt; {  
        return fetch( 
          `https://jsonplaceholder.typicode.com/todos/${todoId}`, 
          { signal: abortSignal } 
        ).then((res) =&gt; res.json() as Promise<todo>);
    },
});</todo>
```

This will cancel the previous request when the `todoId` changes and if the previous request is still in progress.

We can also have multiple request dependencies, for example:

```
limit = signal(10);
query = signal('');

todosResource = resource({
    request: () =&gt; ({ limit: this.limit(), query: this.query() }),
    loader: ({ request, abortSignal }) =&gt; {   
        const { limit, query } = request as { limit: number; query: string };
        return fetch(
          `https://jsonplaceholder.typicode.com/todos?_limit=${limit}&amp;query=${query}`, 
          { signal: abortSignal } 
        ).then((res) =&gt; res.json() as Promise<todo[]>);
    },
});</todo[]>
```

Now, the `todosResource` will make the request based on the `limit` and `query` signals, and the loader function will be able to use those signals to make the request, and anytime the `limit` or `query` signal changes, the `loader` function will be called again.

### What happens when we have a request in progress and update data locally?

If that's the case, the resource API will automatically update the data locally, but cancel the ongoing request.

### Create more reusable resources

By separating reactive values from the loader function, we can move the logic of the `loader` function to a separate function, and store it where we want.

**Before:**

```
todoResource = resource({
    request: this.todoId,
    loader: ({ request: todoId, abortSignal }) =&gt; {  
        return fetch(
          `https://jsonplaceholder.typicode.com/todos/${todoId}`, 
          { signal: abortSignal } 
        ).then((res) =&gt; res.json() as Promise<todo>);
    },
});</todo>
```

**After:**

```
import { ResourceLoaderParams } from "@angular/core";

function todoLoader({ request: todoId, abortSignal }: ResourceLoaderParams<number>): Promise<todo> {
    return fetch(
      `https://jsonplaceholder.typicode.com/todos/${todoId}`, 
      { signal: abortSignal } 
    ).then((res) =&gt; res.json() as Promise<todo>);
}

todoResource = resource({ request: this.todoId, loader: todoLoader });</todo></todo></number>
```

The `todoLoader` can be moved anywhere, and also can be reused by other resources. The `ResourceLoaderParams` type is a type that contains all the information that is needed to make the request, and the `request` parameter is the one that is passed to the loader function.

## RxResource -> The Observable based resource API

Angular has always been about using Observables when it comes to data loading. This means, that we can use Observables to derive the data loading instead of using signals & promises.

In order to make this possible, we can use the `rxResource` function.

```
import { rxResource } from "@angular/core/rxjs-interop";

@Component()
export class MyComponent {
  limit = signal(10);

  todosResource = rxResource({
    request: this.limit,
    loader: (limit) =&gt; {
      return this.http.get<todo[]>(
        `https://jsonplaceholder.typicode.com/todos?_limit=${limit}`
      );
    },
  });
}</todo[]>
```

This will make the request based on the limit signal, and the `loader` function will be able to use the `limit` value to make the request, and same as signals, anytime the limit signal changes, the loader function will be called again and cancel the previous request (same as switchMap behavior in RxJs)

And same as we can change local state with the signals, we can also change the local state with the observables implementation in the `rxResource` function.

## Summary

We have 2 new primitives \[**resource**, **rxResource**\] that will help us make our life easier when dealing with data loading in Angular. These primitives have been requested for so long now, and will land in v19 as developer previews.

PR link: [https://github.com/angular/angular/pull/58255](https://github.com/angular/angular/pull/58255)
