Search code examples
angularresolver

Trying to get specific parts of data inside route resolver Angular


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


Solution

  • 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"])
          )
        )
      }
    }