Angular 8 getRole не является функцией во вложенном объекте - PullRequest
1 голос
/ 27 октября 2019

У меня есть API, который возвращает мне информацию Profile, и я получаю ее в своем HTTP-сервисе. Вложенный объект User имеет метод getRole(). Но когда я пытаюсь вызвать этот метод, я получаю

ОШИБКА TypeError: _co.profile.user.getRole не является функцией

Когда я получаю Userиз моего другого сервиса, который возвращает только сущность User, я могу вызвать эту функцию без проблем.

Чего мне не хватает?

Модель

export class Profile {
  user: User;
  apiKeys: ApiKey[];
}

export class User {
  user: string;
  firstname: string;
  surname: string;
  email: string;
  role: Role;
  active: boolean;

  getRole() {
    switch (this.role) {
      case Role.READ: {
        return "READ";
      }
      case Role.WRITE: {
        return "WRITE";
      }
      case Role.ADMIN: {
        return "ADMIN";
      }
      default : {
        return "READ";
      }
    }
  }
}

ProfileService.ts

getProfile(): Observable<Profile> {
    return this.http.get<Profile>(this.profileUrl).pipe(catchError(this.handleError));
}

Component.ts

profile: Profile;
isProfileAvailable:boolean = false;

ngOnInit() {
  this.settingsService.getProfile().subscribe(profile => {
    this.profile = profile;
    this.isProfileAvailable = true;
   });
}

Component.html

<p-fieldset [legend]="Profile" *ngIf="isProfileAvailable">
    <div><b>User: </b>{{profile.user.firstname}}</div>
    <div><b>E-mail: </b>{{profile.user.email}}</div>
    <div><b>Role: </b>{{profile.user.getRole()}}</div>
</p-fieldset>

Ответы [ 3 ]

1 голос
/ 27 октября 2019

Вызов http.get<Profile> автоматически не инициализирует объект типа Profile, поэтому свойство user также не является объектом типа User и не имеет метода getRole.

Вы можете использовать Object.assign для инициализации объектов и их свойств. И поскольку существует два типа классов (Profile, User), оба могут расширяться от Base -Класса для обработки назначения свойств для обоих типов.

Модели:

// Use a Base class to assign all properties with objects both of type Profile and User
class Base {
    constructor(properties?: any) {
        (Object as any).assign(this, properties);
    }
}

export class User extends Base {
    user: string;
    firstname: string;
    surname: string;
    email: string;
    role: Role;
    active: boolean;

    getRole() {
        switch (this.role) {
            case Role.READ: {
                return "READ";
            }
            case Role.WRITE: {
                return "WRITE";
            }
            case Role.ADMIN: {
                return "ADMIN";
            }
            default : {
                return "READ";
            }
        }
    }  
}

export class Profile extends Base {
    user: User;
    apiKeys: ApiKey[];

    // take advantage of Object.assign
    // to initialize an instance of type Profile 
    // along with it's property user
    constructor(properties?: any) {
        super(properties);
        this.user = new User(properties.user);
    }
}

ProfileService.ts

getProfile(): Observable <Profile> {
    return this.http.get<Profile>(this.profileUrl).pipe(catchError(this.handleError));
}

Component.ts

profile: Profile;
isProfileAvailable:boolean = false;

ngOnInit()
{
    this.settingsService.getProfile().subscribe(profileData => {
        // assuming that profileData looks like this:
        /*
        {
            user: {
                user: 'user',
                firstname: 'firstname',
                surname: 'surname',
                email: 'email',
                active: true
            }
        }
        */
        this.profile = new Profile(profileData);
        this.isProfileAvailable = true;
    });
}
1 голос
/ 06 ноября 2019

Blauharley ответ работал как шарм.

Однако, поскольку у меня все мои модели в отдельных файлах, мне пришлось экспортировать базовый класс:

export class Base {
    constructor(properties?: any) {
        (Object as any).assign(this, properties);
    }
}

Все работает как положено.

0 голосов
/ 27 октября 2019

В настоящее время вы не создаете экземпляры своего класса, поэтому метод класса getRole() недоступен. С this.http.get<Profile> вы просто сообщаете компилятору, что то, что вы ожидаете от API, соответствует вашему классу, оно фактически не создает экземпляры вашего класса или подкласса User.

Вам необходимо добавить конструкторк вашим классам со свойствами и фактически создайте экземпляров вашего класса. Вот упрощенный пример:

export class User {
  role: string;

  constructor(role: string) {
    this.role = role;
  }

  getRole() {
    switch (this.role) {
      case 'READ': {
        return "READ";
      }
      case 'WRITE': {
        return "WRITE";
      }
      default: {
        return "READ";
      }
    }
  }
}

Затем необходимо создать экземпляр вашего класса, чтобы иметь доступ к методам класса:

ngOnInit() {
  let user = new User('WRITE');
  console.log(user.getRole());
}

STACKBLITZ

Кроме того, если бы это был единственный метод в вашем классе, который вам нужен, я бы просто предложил использовать вместо этого интерфейсы и написать автономную функцию, которая проверяет роль, вместо того, чтобы преодолевать трудности, связанные с созданием экземпляров. класса. Это очень самоуверенная вещь, поэтому, если вы хотите использовать классы и методы, специфичные для классов, вам нужно пойти по вышеуказанному пути. Мне просто нравится использовать интерфейсы лично:)

...