Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

No methods in http response object

Object returned by $http.get has no methods. Example: I have my class model

export class Lab {

    constructor(
        public id: number,
        public name: string,
        public description: string,
        public isActive: boolean,
        public classes: Classes[]
    ) { }

    isActive(lab: Lab) {
        return this.isActive;
    }
}

in my service I call http fetching lab

getLab(labId: number) {
    return this.http.get<Lab>(DidacticsServiceUrls.apiRoot + labId).toPromise();
}

and when I get this in some component, method isActive is undefined, so call

lab.isActive();

throws exception. Is there any clean solution for this?

like image 237
kriss Avatar asked Jan 04 '18 20:01

kriss


2 Answers

The server just returns data formed with properties from the defined object. It doesn't actually create an instance of the object.

Try something like this:

this.lab = Object.assign(new Lab(), this.retrievedLab)

Where this.retrievedLab is the data returned from the server.

This should create the object and then copy any of the retrieved properties into it.

like image 141
DeborahK Avatar answered Nov 14 '22 06:11

DeborahK


This version is inspired by @Matjaz Hirsman response (thanks!), with added deep cloning.
Also: it resembles the Decorator pattern more than Serialization (or actually Deserialization).

getLab(labId: number) {
    return this.http.get<Lab>(DidacticsServiceUrls.apiRoot + labId)
    .pipe(Lab.decoratingMap())
    .toPromise();
}

Classes:

export class Lab extends Decorable {
    static instanceType = Lab;

    constructor(
        public id: number,
        public name: string,
        public description: string,
        public isActive: boolean,
        public classes: Classes[]
    ) { super(); }

    isActive(lab: Lab) {
        return this.isActive;
    }
}


class Decorable {
  static instanceType: any;

  /**
   * Convert single entity into fully-fledged object
   * @param source js object
   * @return fully-fledged HalResource
   */
  static decorateSingle(source: any) {
    const target = new this.instanceType();
    for (const key in target) {
      if (source[key]) {
        if (target[key] && typeof target[key] === 'object') {
          target[key] = Object.assign(target[key], source[key]);
        } else {
          target[key] = source[key];
        }
      }
    }
    return target;
  };

  /**
   * Convert entity or array of entities into fully-fledged objects
   * @param response js object (or objects)
   * @return fully-fledged object (or objects)
   */
  static decorate(response: any) {
    if (Array.isArray(response)) {
      return response.map(element => this.decorateSingle(element))
    } else {
      return this.decorateSingle(response);
    }
  }

  /**
   * Rx Map operator decorating the JS objects into fully-fledged objects
   */
  static decoratingMap() {
    return map((response: any) => this.decorate(response));
  }
}
like image 22
ppi Avatar answered Nov 14 '22 07:11

ppi