4
votes

Angular return a error : Error: Uncaught (in promise): TypeError: res.users.subscribe is not a function.

Since this morning, I don't understand what's wrong in my resolve.

UserService.ts

import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';

@Injectable()
export class UsersService {

    private api = 'http://localhost:3000/users';
    private headers = new HttpHeaders();

    constructor(
        private http: HttpClient
    ) {}

     getAllUsers(): Observable<any[]> {
         return this.http.get<any[]>(this.api, {headers: this.headers, responseType: 'json' });
    }
}

UserResolve.ts:

import { Injectable } from '@angular/core';
import { Resolve } from '@angular/router';
import { UsersService } from '../services/users.service';

@Injectable()
export class UsersResolve implements Resolve<any> {

    constructor(private usersService: UsersService) {}

    resolve() {
       return this.usersService.getAllUsers();
    }
}

UserComponent.ts

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';

import {Users} from '../_shared/models/Users';

@Component({
  selector: 'app-user',
  templateUrl: './users.component.html',
  styleUrls: ['./users.component.sass']
})

export class UsersComponent implements OnInit {

    constructor(private route: ActivatedRoute) {}

    public title: string;
    public users: Users[] = [];

    ngOnInit() {
        this.route.data.forEach((res: any): any => {
           this.title = res.title;
           res.users.subscribe(users =>  {
              console.log(users);
              this.users = users;
           });
        });
    }
}

When I log res.users, it return "function UsersResolve()" with not proto subscribe...

The json is Array of Object like :

{
  id: 13246,
  guid: '46ffgd456dfs',
  name: 'John Doe',
  adress: ...
}

Can the problem come from the contents of my json ?

Originally, I wanted to train on the RxJS operator...

4
You don't show your route definition. Are you sure you actually registered the UsersResolve?Jens Neubauer
app.routing const appRoutes: Routes = [ ... { path: 'users', component: UsersComponent, data: { title : 'Liste des Utilisateurs', users : UsersResolve } } ]; @NgModule({ ... providers: [ UsersResolve, UserService ] I had thought otherwise angular would have warned me.Reuno92
Ah, there is the mistake: You assign a reference to the UsersResolve-class to data.users, it will not actually not run that way. See Pavan's answer.Jens Neubauer
Please close your question by clicking the checkmark to the left of the answer that helped you mostVikas

4 Answers

2
votes

You're applying subscribe on Array. You should do it on Observable.

Try to apply below changes.. You can perform operations on data once you understand it's value on console.

UserComponent.ts

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import {Users} from '../_shared/models/Users';

@Component({
  selector: 'app-user',
  templateUrl: './users.component.html',
  styleUrls: ['./users.component.sass']
})

export class UsersComponent implements OnInit {

    constructor(private route: ActivatedRoute) {}

    public title: string;
    public users: Users[] = [];

    ngOnInit() {
        this.route.data.subscribe(data => console.log(data));
    }
}

UPDATE

As mentioned in Comments:

if you've defined routes like this:

const appRoutes: Routes = 
[ ... 
 { path: 'users',
   component: UsersComponent,
   resolve: { 
     users : UsersResolve 
   } 
 } 
];

The you should be able to get the data as:

ngOnInit() {
        this.route.data.subscribe(data => console.log(data['users']));
    }
1
votes

From de angular.io doc:

interface ActivatedRoute {
  snapshot: ActivatedRouteSnapshot
  url: Observable<UrlSegment[]>
  params: Observable<Params>
  queryParams: Observable<Params>
  fragment: Observable<string>
  data: Observable<Data>
  outlet: string
  component: Type<any> | string | null
  get routeConfig: Route | null
  get root: ActivatedRoute
  get parent: ActivatedRoute | null
  get firstChild: ActivatedRoute | null
  get children: ActivatedRoute[]
  get pathFromRoot: ActivatedRoute[]
  get paramMap: Observable<ParamMap>
  get queryParamMap: Observable<ParamMap>
  toString(): string
}

That data is the observable himself. Try:

this.route.data.subscribe(data =>  {
      console.log(data);
   });
});

Remember, subscribe is the ear to an observable voice.

1
votes

The above answers are right on, but I ran into a special case of this.

The method being called was an observable and was used in other parts of the application as an observable, yet when I ran it, it was saying the dreaded subscribe is not a function.

The issue was, I was running in Jasmine unit tests, I had defined a custom mock, and that mock was not returning an observable. In such cases it is easy to goof up the mock and return a different type then the actual function being mocked returns. Correcting my mock fixed my issue.

0
votes

you can access the resolved data in two ways

ActivatedRoute data Property which holds the static and resolved data of the current route
ActivatedRouteSnapshot: the no-observable alternative.

you need to add resolve property to the route configuration, which is an object where each key points to a resolver.

    const appRoutes: Routes = [{ path: 'users', component: UsersComponent, 
         data: { title : 'Liste des Utilisateurs'},
          resolve:{ users : UsersResolve } } 
]

Approach-1

 ngOnInit() {
        this.route.data.subscribe(value=>{

   this.title=value.title;
    this.users=value.user;
});

    }

Approach:2

ngOnInit() {

       this.title=this.route.snapshot.data.title;
        this.users=this.route.data.snapshot.user;


        }

STACKBLITZ DEMO