У меня есть служба, которая содержит метод, который получает список сотрудников:
export class EmployeeService {
private employeesUrl = 'http://localhost:portnum/api/employees';
getEmployees(): Observable<IEmployee[]> {
return this.http.get<IEmployee[]>(this.employeesUrl).catch(this.errorHandler);
}
}
В моем компоненте у меня есть этот фрагмент, который извлекает список сотрудников из моей службы:
employees = [];
constructor(private fb: FormBuilder, private _employeeService: EmployeeService) {
this.transactionForm = fb.group ({
'employee': [null, Validators.required]
});
}
ngOnInit() {
this._employeeService.getEmployees().subscribe(data => this.employees = data, error => this.errorMsg = error);
}
и в моем html-коде у меня есть выпадающий список, который привязывается к списку сотрудников:
<span style = "padding-right:60px;">{{'Employee' | translate}}*
<select [ngModel] = "null" formControlName = "employee" [ngClass] = "displayErrors ? 'inputRedBorder': 'input'" required >
<option value = "null" disabled selected>{{'SelectEmployee' | translate}}</option>
<option *ngFor = "let employee of employees">{{employee}}</option>
</select>
<p class = "error-msg" *ngIf = "displayErrors" name = "errorMsg">
{{'RequiredField' | translate}}</p>
</span>
Однако вместо раскрывающегося списка всех возвращенных сотрудников я получаю следующую ошибку:
ERROR Error: Error trying to diff '[object Object]'. Only arrays and iterables are allowed
at DefaultIterableDiffer.webpackJsonp../node_modules/@angular/core/esm5/core.js.DefaultIterableDiffer.diff (core.js:7495)
at NgForOf.webpackJsonp../node_modules/@angular/common/esm5/common.js.NgForOf.ngDoCheck (common.js:2583)
at checkAndUpdateDirectiveInline (core.js:12368)
at checkAndUpdateNodeInline (core.js:13889)
at checkAndUpdateNode (core.js:13832)
at debugCheckAndUpdateNode (core.js:14725)
at debugCheckDirectivesFn (core.js:14666)
at Object.eval [as updateDirectives] (TransactionPortalComponent.html:23)
at Object.debugUpdateDirectives [as updateDirectives] (core.js:14651)
at checkAndUpdateView (core.js:13798)
Объект представляет собой массив, поэтому я не уверен, почему он говорит, что разрешены только массивы и итерации. Что я делаю не так?
Обновлено:
Ответ от api должен выглядеть так:
{
_employeeList :
[{
_employeeKey : ""employee1""
},
{
_employeeKey : ""employee2""
}],
_errorDetails :
{
_message : ""successful"",
_status : 200
}
}
Но я только возвращаю массив [].
Может быть, это связано с моим интерфейсом? :
export interface IEmployee {
employee: string;
}
@edkeveked Я получаю [] в качестве вывода в консоли. Просто пустой массив. Значит, это может быть проблема с данными API? Как лучше всего справиться с пустыми массивами?
Возможно, вы можете использовать директиву *ngIf перед запуском цикла. Рассмотрим мой ответ ниже






В конструкторе вы внедрили службу как _employeeService, но в методе ngOnInit () вы вызываете this._transactionService.getEmployees (). Это должно быть this._employeeService.getEmployees ().
извините, не проблема. Мне пришлось переименовать некоторые вещи для этого сообщения SO. Я исправил опечатку, но проблема не исчезла.
Мне кажется, что ваши данные возвращаются как объекты, отсюда и ошибка [Object Object]. Ваша HTML-привязка ищет employee.someProp, но вы не привязываетесь к свойству объекта. Вы утешили свои данные в методе ngOnInit, чтобы убедиться, что они возвращаются правильно?
Когда я выводил на консоль, он превратился в пустой массив []
В теге span вы можете указать * ngIf = "employee", если хотите поймать пустой массив и не показывать раскрывающийся список. Затем вы можете добавить дополнительный div или что-то в этом роде с помощью * ngIf = "! Employee", если вы хотите показать что-то вроде «Сотрудники не найдены!». Похоже, у вас может быть ошибка api, если вы возвращаете пустой массив.
Я думаю, что то, как вы выполняете цикл, неверно, поскольку вы хотите иметь тег <option> для каждого сотрудника.
Кроме того, поскольку ваш массив может быть пустым, вы можете сначала проверить, содержит ли массив данные или нет. Возможно, вы можете рассмотреть возможность использования <ng-template> и ng-container.
Получив этот ответ от вашего api, вы должны внести следующие изменения:
услуга
API возвращает JSON, а не массив
getEmployees(): Observable<any> {
return this.http.get<any>(this.employeesUrl).catch(this.errorHandler);
}
составная часть
Получить массив
ngOnInit() {
this._employeeService.getEmployees().subscribe(data => this.employees = data._employeeList, error => this.errorMsg = error);
}
шаблон
Поскольку вы хотите отображать не сам объект, а его значение, вы можете сделать следующее:
<ng-container *ngIf = "employees?.length>0">
<ng-template ngFor let-employee [ngForOf] = "employees">
<option>{{employee._employeeKey}}</option>
</ng-template>
</div>
создать форму INTO функция подписки
Я должен получить ответ в следующем формате: pastebin.com/F3jrYFpS Мне интересно, связано ли это с тем, как я настроил свой интерфейс? Я отредактирую свой пост
Большое спасибо. Это была проблема с форматом объекта json, и вы правы, для шаблона мне нужно добавить _employeeKey для привязки к правильному полю. Большое спасибо за твою помощь! Но стоит ли в будущем создавать интерфейс, соответствующий json, и делать его строго типизированным?
Я пришел из фона javaScript, поэтому, честно говоря, даже если мне нравится набирать TypeScript, я не люблю сильно ограничивать себя этим. Так что, я бы сказал, это вопрос предпочтений. Вы должны поступать так, как считаете нужным :)
Не могли бы вы сделать
console.info(JSON.stringify(this.employees))после подписки на сервис и опубликовать результат здесь?