#Resources lack a way of deriving one from the other

3 messages · Page 1 of 1 (latest)

dense vale
#

Hi all.

I started using resources in a really small project, and I already often find myself in a situation where I find them a bit annoying to use due to the lack of derivation.

Let me take an example: A service returns a resource. I want to display that resource value in my component, but the value needs to be transformed first. Problem: There is no way to transform the resource into another resource. The only possibility is to transform the value of the resource.

So I'm left with three choices.

  1. Create another child component which takes the value of the resource as input, and use a computed to transform it in that child component. Quite clean, but a bit annoying when the parent component is already really simple and doesn't really benefit from being split in two.
  2. Add a computed signal, which reads resource.value()! and transforms it (note the ! operator). But it's not obvious that this signal is derived from the resource value and can only be used inside a @if (resource.hasValue()). We lose the benefit of the hasValue guard.
  3. Add a computed signal, which reads resource.hasValue() and resource.value() and transforms it, or returns undefined if there is no value. But then either I use @if (resource.hasValue()) in the template, and I still need to check if the computed signal value is not undefined, or I only test if the computed signal has a value, but it's weird to have two different sources that don't seem related.
#

What I would like to be able to do is the following:

@Component({
  template: `
    @if (derivedResource.hasValue()) {
      {{ derivedResource.value().transformedFoo }}
    } @else if (derivedResource.isLoading()) {
      Loading...
    } @else if (derivedResource.error()) {
      Oops
    }`
})
export class FooComponent {
  private readonly fooResource: Resource<Foo | undefined> = inject(FooService).getFoo();
  readonly derivedResource: Resource<TransformedFoo | undefined> = mapResource(fooResource, value => transform(value)); // transform is only called if the resource has a value
}

How do you deal with that problem?
Has anyone created such a mapResource utility?
If anyone from the team reads this, would you consider this a valuable thing to add in the framework?

blazing frost
#

@dense vale