Skip to content

RFC: Builder-linke Pattern for Creating Mutations #225

@manfredsteyer

Description

@manfredsteyer

Usually, we don't want to define details of the underlying HTTP call in the store. It's more usual to move this into a service:

readonly save() {
  return httpMutation<Flight, Flight>( (flight) => ({
      url: 'https://...',
      method: 'POST',
      body: flight,
  }));
}

However, the store needs to be able to specify the success and error handlers, as well as the flattening operator to use. To streamline this task, this RFC proposes a builder-like style for specifying these details via setters in the store:

withMutations((store) => ({
  save: store._flightService.save()
    .withOnSuccess: (result: Flight) => {
      patchState(store, { flightValue: result });
      store._snackBar.open('Flight saved!', 'OK');
    }
    .withOnError: (error: any) => {
      console.error('Error saving flight:', error);
      store._snackBar.open('Error saving flight', 'OK');
    },
    .withOperator(mergeOp),
  }),
),

Alternative

Providing types that expose all mutation options but the operation (rxMutation) or request (httpMutation) so that the caller can pass these options to the service:

export type MutationSettings<Params, Result> = Omit<
  HttpMutationOptions<Params, Result>,
  'request'
>;

In this case, the service method can be configured by the caller:

createSaveMutation(options: MutationSettings<Flight, Flight>) {
  return httpMutation({
    ...options,
    request: (flight) => ({
      url: 'https://demo.angulararchitects.io/api/flight',
      method: 'POST',
      body: flight,
    }),
  });
}

In the store, such a method could be called as follows:

withMutations((store) => ({
  save: store._flightService.createSaveMutation({
    onSuccess: (result: Flight) => {
      patchState(store, { flightValue: result });
      store._snackBar.open('Flight saved!', 'OK');
    },
    onError: (error: any) => {
      console.error('Error saving flight:', error);
      store._snackBar.open('Error saving flight', 'OK');
    },
  }),
})),

One disadvantage of this solution is that it adds one more level of nesting when calling the service method.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions