Error encountered in Ngrx data service when using Angular resolver

I have successfully implemented an NGRX Data entity service and now I'm looking to preload data before accessing a route by using a resolver.

import { Injectable } from "@angular/core";
import {
  ActivatedRouteSnapshot,
  Resolve,
  RouterStateSnapshot,
} from "@angular/router";
import { Observable, race } from "rxjs";
import { filter, first, tap, mapTo } from "rxjs/operators";
import { ExerciseEntityService } from "./exercise-entity.service";

@Injectable()
export class ExercisesResolver implements Resolve<boolean> {
  constructor(private exercisesService: ExerciseEntityService) {}

  resolve(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Observable<boolean> {
    return this.exercisesService.loaded$.pipe(
      tap((loaded) => {
        if (!loaded) {
          this.exercisesService.getAll();
        }
      }),
      filter((loaded) => !!loaded),
      first()
    );
  }
}

The challenge arises when the service responds with an error. How can we manage errors while still resolving the route? One approach I tried is using the following code:

import { Injectable } from '@angular/core';
import {
  ActivatedRouteSnapshot,
  Resolve,
  RouterStateSnapshot
} from '@angular/router';
import { Observable, race } from 'rxjs';
import { filter, first, tap, mapTo } from 'rxjs/operators';
import { ExerciseEntityService } from './exercise-entity.service';

@Injectable()
export class ExercisesResolver implements Resolve<boolean> {
  constructor(private exercisesService: ExerciseEntityService) {}

  resolve(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Observable<boolean> {
    return race(
      this.exercisesService.loaded$.pipe(
        tap((loaded) => {
          if (!loaded) {
            this.exercisesService.getAll();
          }
        }),
        filter((loaded) => !!loaded),
        first()
      ),
      this.exercisesService.errors$.pipe(mapTo(true))
    );
  }
}

Answer №1

Struggling through various approaches involving combineLatest, mergeMap, race, and other operators led to solving the problem in this particular way:

import { Injectable } from '@angular/core';
import {
  ActivatedRouteSnapshot,
  Resolve,
  RouterStateSnapshot
} from '@angular/router';
import { Observable, Subscriber } from 'rxjs';
import { filter, first, tap } from 'rxjs/operators';
import { ExerciseEntityService } from './exercise-entity.service';

@Injectable()
export class ExercisesResolver implements Resolve<boolean> {
  constructor(private exercisesService: ExerciseEntityService) {}

  resolve(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Observable<boolean> {
    const loadExercises = (subscriber: Subscriber<boolean>) => {
      this.exercisesService.loading$
        .pipe(
          filter((loading) => !loading),
          first()
        )
        .subscribe({
          next: (loading) => {
            subscriber.next(true);
            subscriber.complete();
          }
        });
      this.exercisesService.getAll();
    };

    const resolve$ = new Observable<boolean>((subscriber) => {
      this.exercisesService.loaded$
        .pipe(
          tap((entitiesLoaded) => {
            if (!entitiesLoaded) {
              loadExercises(subscriber);
            } else {
              subscriber.next(true);
              subscriber.complete();
            }
          })
        )
        .subscribe();
    });

    return resolve$;
  }
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is there a way to identify packages that rely on Angular versions greater than 6.x?

Currently, I am working on a project that is using Angular 5.x, and my task is to upgrade it to version 6.x. It has been almost two weeks since I started this process, struggling to understand how to handle the upgrades using NPM. Unfortunately, I have bee ...

What is the best way to include the parameter set in the interceptor when making a post request?

-> Initially, I attempt to handle this scenario in the axios request interceptor; if the parameter is uber, then utilize a token. If the parameter is not uber, then do not use a token. -> Afterward, how can I specify uber as a parameter in the custo ...

Tips for retrieving additional values from a chosen variable in Angular 10

Here is an array I have: export const Glcode = [ { id: 1, Type: 'Asset', Name: 'Cash at Head Office', code: '10018' }, { id: 2, Type: 'Asset', Name: 'POS ACCOUNT ', code: '10432' }, { ...

How can I move the cursor to the beginning of a long string in Mat-autocomplete when it appears at the end?

I'm struggling to figure out how to execute a code snippet for my Angular app on Stack Overflow. Specifically, I am using mat-autocomplete. When I select a name that is 128 characters long, the cursor appears at the end of the selected string instead ...

Angular 2 GET request returns a 404 error

I have been attempting to reproduce the ngPrime datatable demo from this Github repository. Currently, I am working with the most recent version of Angular (4) and using angular-cli in development mode. Placing a JSON file into my app folder where the serv ...

Error encountered when utilizing cursor in Prisma

I am currently utilizing Prisma version 4.2.1 within a Next.js API Route to implement cursor-based pagination for posts. Upon passing the cursor to the API endpoint, I encounter an error message (500) in the console: TypeError: Cannot read properties of u ...

Navigating JSON data with unexpected fields in Typescript and React.js

Looking to parse a JSON string with random fields in Typescript, without prior knowledge of the field types. I want to convert the JSON string into an object with default field types, such as strings. The current parsing method is: let values = JSON.parse ...

Can you conduct testing on Jest tests?

I am in the process of developing a tool that will evaluate various exercises, one of which involves unit-testing. In order to assess the quality of tests created by students, I need to ensure that they are effective. For example, if a student provides the ...

Ways to modify the server port beyond 3000?

After completing the Angular 2 tutorial, I encountered an issue with changing the localhost port from 3000 to 8000. I noticed a line in my package.json file that reads "start": "concurrent \"npm run tsc:w\" \"npm run lite\" " which I th ...

Utilize fixed values in type declaration

Strange Behavior of Typescript: export type MyType = 0 | 1 | 2; The above code snippet functions correctly. However, the following code snippet encounters an issue: export const ONE = 1; export const TWO = 2; export const THREE = 3; export type MyType = O ...

Can you identify the specific syntax for a 'set' function in TypeScript?

I have a TypeScript function that looks like this: set parameter(value: string) { this._paremeter = value; } It works perfectly fine. For the sake of completeness, I tried to add a type that specifies this function does not return anything. I experimen ...

When interacting with a <select> element, the behavior of test script execution varies between Firefox and Chrome

I've encountered an unusual problem that I need help describing and solving. Your assistance is greatly appreciated! The issue I'm facing involves Testcafe behaving differently when running the same test script on various browsers. testcafe: ...

What might be causing my observable to fail to return a value?

I'm currently utilizing an API known as ngx-pwa localstorage, which serves as a wrapper for an indexeddb database. Within my Angular project, I have a service that interacts with this database through a method called getItem: getItem(key: string) { ...

Is it possible for me to offer a service for a nested modal dialog component without replacing the existing service that already has the same token provided

Imagine I inject service 'Z' into component 'A', and from there it spawns a dialog component 'B' that also needs access to service 'Z'. If the service 'Z' needs to be a fresh instance in component 'B&a ...

There are no properties shared between type 'dateStyle: string' and type 'DateTimeFormatOptions'

"typescript": "^4.0.3" Can anyone help me resolve the TypeScript error I am encountering in the code below?: components/OrderListItem.tsx const newedate = (_date) => { const options = {dateStyle: 'medium'}; //{ weekday: ...

What is the process for exporting the reducer function and integrating it into the storeModule.forRoot within an Angular application?

Recently, I started delving into ngrx and decided to educate myself by going through the official documentation on their website ngrx.io. During this exploration, I came across a puzzling piece of code in one of their reducers. The file in question is cou ...

Error with the type of CanvasGradient in the NPM package for converting text to image

I attempted to generate an image using a specific text by utilizing npm's text-to-image package, but encountered an error during typescript compilation. The errors I encountered upon running the typescript compilation command are related to files with ...

Error: Issue determining the type of variable. Unable to eliminate type 'any'

I am trying to load some widgets from a template object (possibly JSON in the future). Here's an example: type RectangleTemplate = { name: 'Rectangle'; props: { width: number; height: number; } }; type ButtonTemplate = { nam ...

Locating Items in an Array using Angular 5 and Forming a New Array with the Located Objects

Looking for a way to extract objects from an array that have the type "noActiveServiceDashboard" and "extraAmountDashboard". I want to create a new array with only these two entries in the same format. I've attempted using .find() or .filter() method ...

In TypeScript, how to refer to the type of the current class

Is there a way to reference the current class type in the type signature? This would allow me to implement something like the following: export class Component{ constructor(config?: { [field in keyof self]: any }) { Object.assign(this, config) ...