Angular 4 Компонентная переменная типа Item, инициализированная в ответе подписки, не имеет методов, определенных в классе Item. - PullRequest
0 голосов
/ 24 июня 2018

Я работаю над проектом Angular для нового внутреннего приложения. Хотя у меня есть некоторый опыт работы с AngularJS, я почти новичок, когда дело доходит до Angular 2+. Проблема, с которой я столкнулся, которую я не могу понять, заключается в установке некоторых переменных класса компонента внутри обратного вызова подписки в блоке ngOnInit. Я буду немного абстрактен с моими деталями, но я надеюсь, что он предоставит достаточно контекста, чтобы передать проблему.

У меня определен тип предмета:

export class Item {
    name: String;
    checked: boolean = false;

    // this is a simplification of the actual type and method, I'm aware this seems unnecessary
    toggle(set: boolean = false): void {
        this.checked = !this.checked || set;
    }
}

В моем компоненте я объявил массив элементов, используя обратный вызов подписки на restful-сервис.

import ...
@Component({
  templateUrl: './item.component.html',
  styleUrls: [ './item.component.less',
  providers: [ ItemService ]
})
export class ItemComponent implements OnInit {
  items: Item[];
  allChecked: boolean = false;

  constructor(private itemService: ItemService) { }

  ngOnInit() {
    this.itemService.getItems().subscribe(
      (response) => {
        this.items = items;
      }
    );
  }

  checkAll(): void {
    this.allChecked = !this.allChecked;

    for(let item of this.items) {
      item.toggle(allChecked);
    }
  }

В html (а также в функции "checkAll ()" компонента выше) я ссылаюсь на метод, определенный для типа элемента, следующим образом:

<input ... (change)="checkAll()" />
...
<tr *ngFor="let item of items; index as i">
  <td>
    <input ... (change)="item[i].toggle()" />
  </td>
</tr>
...

Ранее у меня был массив объектов, которые были смоделированы в компонентном блоке ngOnInit. Когда это было так, эти вызовы методов выполнялись нормально. Только после замены фиктивных данных фактическим вызовом службы restful у меня возникают проблемы с достижением метода toggle (). Я получаю сообщение о том, что метод, который я пытаюсь вызвать для моего типа элемента, не определен.

Я понимаю, что в javascript / typcript область видимости немного сложная, но, поскольку я использую синтаксический формат сахарной стрелки для обратного вызова подписки, «this» должно ссылаться на правильный контекст, да? Кроме того, поскольку я был в растерянности, я также попытался использовать that = this; вне вызова службы, а затем сослаться на «что» внутри обратного вызова, чтобы убедиться, что я устанавливал свойство items в контексте внешнего класса. В любом случае, кажется, что как только я выхожу из контекста обратного вызова подписки, любое представление об элементах возвращается как неопределенное. Почему это? Я упускаю какую-то ключевую точку Angular 2 +?

Редактировать: я понимаю, что был слишком глубоко в дыре и ошибочно принимал, что в моих средах IDE отсутствовало надлежащее отображение (показ данных компонента как неопределенных при отладке, даже если это не так), когда на самом деле данные были в виде json без каких-либо определений метода. Я добавил код в этот пост и изменил текст / заголовок, чтобы отразить это.

1 Ответ

0 голосов
/ 24 июня 2018

Вы получаете ответ JSON от вашего сервисного вызова, а не экземпляры вашего Item класса.Как простые объекты данных, они не имеют определений методов ItemImpl.Поэтому вам нужно сопоставить каждый объект с экземпляром класса.

interface Item {
  id: string;
  name: string;
}

class ItemImpl implements Item {
  id: string;
  name: string;

  constructor(item: Item) {
    this.id = item.id;
    this.name = item.name;
  }

  someMethod() {
    // ...
  }
}

Затем сопоставить результат с HTTP-вызовом:

return this.http.get<Item[]>(this.myItemsUrl)
  .pipe(
    map(items => items.map(i => new ItemImpl(i)))
  );

На мой взгляд, было бы лучше поместить стильлогика (someMethod()) в службу вместо Item класса данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...