2

I am trying to use a resolver to attach data to my route when routing to specific items within a collection. I had my data stored locally in a service and used a method on the service to find the item whose name matched the route param I was searching. This worked perfectly, but then I changed it to try use a call to the database for information instead. Now I am unable to figure out how to sort through the returned data for the specific item I want in the resolver service.

Here is my resolver service:

@Injectable()
export class FoodResolver implements Resolve<any> {
    constructor(private foodService: FoodService) {}

    resolve(route: ActivatedRouteSnapshot) {
        this.foodService.getFood().subscribe((data) => {
            return data.find((food) => {
                return food.name == route.params["name"];
            })
        })
    }
}

getFood makes a simple call: return this.http.get<Array<FoodModel>>("/api/foods") and I am using InMemoryWebApi to mock the database.

In my component I get the data in ngOnInit:

    ngOnInit(): void {
        this.food = this.route.snapshot.data["food"];
    }

If someone could point me to where I'm going wrong it would be much appreciated. I added console logs throughout. The order:

ngOnInit: food = undefined.

Html render error: Cannot read property name of undefined.

Food Resolver: Logs correct food list and correct item I want to find.

Html render error: Cannot read property name of undefined.

When I just return the getFood method without altering it so that it displays the entire collection of foods it works perfectly. Because of this and the delay on the foodResolver logs i assumed the resolver needs to return an observable. So I wrapped the function in a new observable:

resolve(route: ActivatedRouteSnapshot) {
    const observable = new Observable((observer) => {
        observer.next(
            this.foodService.getFood().subscribe((data) => {
                return data.find((food) => {
                    return food.name == route.params["name"];
                })
            })
         );
         observer.complete();
       })
       return observable;
    }

In doing this all the errors are gone, but no information displays. In ngOninit food is a subscriber. And now I'm out of ideas. If someone could assist me it would be very much appreciated. Thank you.

Sidenote: I would prefer not to filter the list inside the component itself for reusability sake if possible. Also I do not have my data set out with id's so cannot call http.get("/food/lasagna") for example

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189

1 Answers1

1

Signature of resolve suggests returning an Observable<T>/Promise<T>. You're not returning anything.

Try this:

import { map } from 'rxjs/operators';
...

@Injectable()
export class FoodResolver implements Resolve < any > {
  constructor(private foodService: FoodService) {}

  resolve(route: ActivatedRouteSnapshot) {
    return this.foodService.getFood().pipe(
      map(
        data => data.find(food => food.name == route.params["name"])
      )
    )
  }
}
SiddAjmera
  • 38,129
  • 5
  • 72
  • 110