Как определить вложенный объект в модели? (угловой2/машинопись)

Я играю с Angular2 и надеялся, что кто-нибудь может дать совет, как этого добиться;

Например, если моя модель в настоящее время выглядит так для сотрудника:

export class Employee {
    constructor(
        public firstName: string,
        public lastName: string,
        public email: string,
        public days: string,
        public hours: string, 
    ){}
}

и я хочу поместить дни/часы в свой собственный объект, как это может быть достигнуто?

(т.е. как..)

public availability: {
        public days: string,
        public hours: string
},

и тогда останется ли запрос http get таким же, как показано ниже?

getEmployees() {
      return this.http.get('...')
             .map((response: Response) => {
                 const data = response.json().obj;
                 let objs: any[] = [];

                 for(let i = 0; i < data.length; i++) {
                     let employee = new Employee(
                     data[i].firstName,
                     data[i].lastName, 
                     data[i].email, 
                     data[i].availability.days,
                     data[i].availability.hours
                     );

                     objs.push(employee)
                 }
                 return objs
             })
          }

Просто чтобы уточнить, я хотел бы, чтобы мой запрос на получение возвращал что-то вроде;

var obj = {
    firstName: "test",
    lastName: "test",
    email: "test",
    availability: {
      days: "test",
      hours: "test"
    }
  }

Надеюсь, кто-то может помочь! Я пытался осмотреться, но не нашел ничего, что могло бы помочь.


person confusedandenthused    schedule 16.11.2016    source источник


Ответы (3)


Что-то вроде этого

export class Employee {
    constructor(
        public firstName: string,
        public lastName: string,
        public email: string,
        public availability: Availability // refer to type Availability  below
    ){}
}

export class Availability {
    constructor(
        public days: string,
        public hours: string
    ){}
}

Запрос на получение Http должен оставаться прежним, а затем меняться в зависимости от того, как вы создаете новый экземпляр сотрудника.

let employee = new Employee(
    data[i].firstName,
    data[i].lastName,
    data[i].email,
    new Availability(
          data[i].availability.days,
          data[i].availability.hours
    )
);
person Michael    schedule 16.11.2016
comment
Привет, я получаю ошибки, используя этот пример - Cannot find name 'Availability'. это то, что отображается в сервисе, а в файле класса - ';' expected. Я думаю, что export class Availability не будет виден внутри класса Employee, если вы его не импортируете? - person confusedandenthused; 16.11.2016
comment
@confusedandenthused да, извините, у класса Availability должен быть свой конструктор, я его исправил, затем импортируйте класс Availability в класс Employee и в свой сервис. - person Michael; 17.11.2016
comment
Спасибо - это заработало! Также стоит отметить, что вы должны импортировать новый класс в компонент, чтобы заставить его работать. - person confusedandenthused; 17.11.2016
comment
что, если model имеет сто собственности? Вы не можете сделать это так. - person slideshowp2; 03.08.2017
comment
Вам нужно определить интерфейсы вместо классов, чтобы работать правильно. - person lentyai; 11.10.2017

Для тех, кто обнаружит это пару лет спустя, есть полезная библиотека, которая может помочь с этим, называемая class-transformer.

Использовать эту библиотеку было проще всего: https://github.com/typestack/class-transformer

import { Type } from 'class-transformer';

export class Employee {
    firstName: string;
    email: string;
    days: string;
    hours: string;

    @Type(() => Availability)
    availablity: Availablity

    constructor(args: Employee) {
      Object.assign(this, args);
    }
}

export class Availability {
    days: string;
    hours: string;

    constructor(args: Availability) {
      Object.assign(this, args);
    }
}

Несколько вещей изменилось:

  1. Использование декоратора @Type исходит из модуля class-transformer. Это позволяет преобразовывать вложенные объекты. Вот документация: https://github.com/typestack/class-transformer#working-with-nested-objects
  2. Мы добавили constructor, который позволяет вам создавать экземпляры этих классов и передавать им атрибуты их собственных соответствующих типов. Взгляните на этот пост https://stackoverflow.com/questions/50551649/converting-httpclient-answer-to-model-objects-angular-6 поскольку это проливает больше света на то, что здесь происходит.

Затем в вашей службе вот как изменяется ваш код:

import { plainToClass } from 'class-transformer';
import { Employee } from './Employee'

getEmployees() {
  return this.http.get('...')
    .map((response: Response) => plainToClass(Employee, response.json().obj as Employee[]))

plainToClass возьмет необработанный ответ JSON и преобразует его в экземпляры вашего класса сотрудников. Если вы выведете из консоли результат getEmployees(), вы увидите, что он возвращает массив сотрудников, каждый из которых имеет атрибут с именем availability типа «Доступность».

person jetset    schedule 30.09.2018

Лично я сделал (для проекта Ionic) что-то вроде

export class Availability {
    days: string  = "";
    hours: string = "";
}

export class Employee {
    firstName: string = "";
    lastName:  string = "";
    email:     string = "";

    availability = new Availability()
}

Поэтому, если я использую эти модели в <form>, я получаю пустую структуру этого класса Employee.

Это также работает, когда я объявляю такие переменные, как employeeObservable : Observable<Employee[]>;, например, когда я запрашиваю базу данных firebase...

person Ricky Levi    schedule 05.10.2018