4

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? Commented Jun 17, 2018 at 16:55
  • 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. Commented Jun 17, 2018 at 17:06
  • 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. Commented Jun 17, 2018 at 17:38
  • Please close your question by clicking the checkmark to the left of the answer that helped you most Commented Jun 24, 2018 at 18:12

4 Answers 4

2

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']));
    }
Sign up to request clarification or add additional context in comments.

2 Comments

It log same thing : Object { title: 'user list, users : function UsersResolve() }
I thought you've passed this static data as you mentioned in comments. it should be.. { path: 'users', component: UsersComponent, resolve: { users : UsersResolve } }... let me update the answer
1

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 Comment

Props for the last line. Describes Subscribe observable in one line.
1

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.

Comments

0

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.