1

I'm new in Angular. I've a class called User:

export class User {
  private id: number;
  private name: string;
  private surname: string;

  get Id(): number {
    return this.id;
  }
  set Id(newId: number) {
    this.id = newId;
  }

  get Name(): string {
    return this.name;
  }
  set Name(newName: string) {
    this.name = newName;
  }

  get Surname(): string {
    return this.surname;
  }
  set Surname(newSurname: string) {
    this.surname = newSurname;
  }
}

...a function to retrive an array of user:

  getValues() {
    this.usersService.getUsers()
      .subscribe((users: User[]) => this.dataSource = users);
  }

and a method to retrive the users array from backend WebApi:

getUsers(): Observable<User[]> {
    return this.http.get<User[]>(this.usersSearchUrl)
      .pipe(
      tap(users => this.log(`fetched users`)),
      catchError(this.handleError('getUsers', []))
      );
  }

finally the json returned from the webapi:

[{"id":"1","name":"Alberico","surname":"Gauss"},{"id":"2","name":"Anassimandro","surname":"Dirac"},{"id":"3","name":"Antongiulio","surname":"Poisson"}]

I would have expected that the call would automatically mapped the User class, instead it only gives me an array of type User, in fact if I write something in my component .subscribe((utenti: Utente[]) => console.log(utenti[0].Surname)); the console writes me "undefined". Can you tell me where I'm wrong? Thanks

Nathan Cooper
  • 6,262
  • 4
  • 36
  • 75

2 Answers2

3

You are retrieving JSON from your backend, as is expected. A Javascript (or typescript) class is not the same thing.

When the JSON is returned, it can be automatically converted into a simple JSON object in Javascript but it will NOT include all your getters and setters. So these class methods are not available, which is why you get undefined.

Remove all the getters and setters and add a constructor. Then you can just call Surname directly as a property and it will return the value (since it will then just be a plain JSON object).

export class User {
  constructor() {
  }

  public id: number;
  public name: string;
  public surname: string;
}

Or without a constructor, and just declare the properties directly:

export class User {    
  public id: number;
  public name: string;
  public surname: string;
}

Or you could also use an interface:

export interface User {   
  id: number;
  name: string;
  surname: string;
}

You can read more about this issue here and here.

Igor
  • 60,821
  • 10
  • 100
  • 175
rmcsharry
  • 5,363
  • 6
  • 65
  • 108
  • 1) You can't specify an access modifier on a field on an interface. 2) For the purposes of your examples it would also be best to remove the `private` access modifier on the class members as well otherwise you could never access them from outside which is what you are describing the OP should do. – Igor Mar 21 '18 at 14:48
  • 1
    See my last change, you can't put an access modifier on the members of an interface. An interface represents a contract and nothing in the contract can be marked as private otherwise what would be the point. If you do put an access modifier on a member of an interface the typescript transpiler will show an error. Now it all looks good (+1 from me). – Igor Mar 21 '18 at 15:33
  • @Igot Thanks again...was too busy elsewhere to give this my proper attention. – rmcsharry Mar 21 '18 at 16:08
-2

I think in component ts use like this code:

 users: User[];
  constructor(
    private us: usersService,
    public auths: AuthService
  )

    this.us.getUsers.subscribe(
      users=> {
        this.users= users.map((user) => {
          return new User(user);
        });
      }
    );

In service I think to write:

  public getUsers(): Observable<User[]> {

    let headers = new Headers();
    headers.append('x-access-token', this.auth.getCurrentUser().token);

    return this.http.get(Api.getUrl(Api.URLS.getUsers), {
      headers: headers
    })
      .map((response: Response) => {
        let res = response.json();

        if (res.StatusCode === 1) {
          this.auth.logout();
        } else {
          return res.StatusDescription.map(user=> {
            return new User(user);
          });
        }
      });
  }

For me this logic work perfect. I hope to help you with this code

Lonna
  • 355
  • 1
  • 6
  • 21