Я создаю приложение Angular с серверной частью Node. Вот мои соответствующие части server.js с конечными точками REST:
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var cors = require('cors');
var mysql = require('mysql');
const con = mysql.createConnection({
host: 'localhost',
user: 'myusername',
password: 'mypass',
database: 'somedb'
});
con.connect((err) => {
if (err) throw err;
console.info('Connected!');
});
app.use(bodyParser.json());
app.use(cors());
app.route('/api/levels').get((req, res) => {
con.query('SELECT * FROM level', (err, rows) => {
if (err)
res.send(JSON.stringify({ "status": 500, "error": err, "response": null }));
else
res.send(JSON.stringify({ "status": 200, "error": null, "response": rows }));
});
});
...
Эта часть работает, я протестировал ее через Postman и получил следующий ответ:
{
"status": 200,
"error": null,
"response": [
{
"id": 1,
"title": "A1.1"
},
{
"id": 2,
"title": "A1.2"
},
... // the rest of the rows
]
}
Угловой сервис:
@Injectable()
export class LevelService {
constructor(private http: HttpClient) {}
public getAll() {
return this.http.get('http://localhost:8000/api/levels/');
}
...
}
Служба вызывается в компоненте:
@Component({
selector: 'app-level-list',
templateUrl: './level-list.component.html',
styleUrls: ['./level-list.component.css']
})
export class LevelListComponent implements OnInit {
private levels: any[];
constructor(private levelService: LevelService) { }
ngOnInit() {
this.levelService.getAll().subscribe((data: any[]) => this.levels = data);
}
}
Данные используются в шаблоне компонента:
<ul class = "level-list">
<li *ngFor = "let level of levels">
<app-level-list-item [level] = "level">
</app-level-list-item>
</li>
</ul>
И, наконец, он должен отображаться на главной странице:
<div style = "text-align:center">
<h1>{{ title }}</h1>
</div>
<p>{{introText}}</p>
<app-level-list></app-level-list>
Однако, когда я открываю страницу, данные не отображаются, а в консоли появляется ошибка:
ERROR Error: Cannot find a differ supporting object '[object Object]' of type 'object'.
NgFor only supports binding to Iterables such as Arrays.
Что я делаю неправильно?
Попробуйте это: (data: any []) => this.levels = data.response





Это не похоже на то, что ваш ответ службы является типом массива, а скорее:
interface ServiceResponse {
status: number;
error: any; // not apparent of the type
response: Level[];
}
Я думаю, что вам нужно изменить свой метод getAll, чтобы отобразить его, чтобы ответ был вашим Level[] вместо ServiceResponse:
public getAll(): Observable<Level[]> {
return this.http.get<ServiceResponse>('http://localhost:8000/api/levels/')
.map(res => res.response);
}
Дать согласие. Мне кажется, причина в этом.
HTTP-запрос возвращает вам тип ответа, и фактические данные, которые вы отправили, находятся в его теле. Чтобы получить его, используйте метод .json (), и после этого вы можете получить доступ к своему массиву, например к свойству, как ребята, упомянутые выше.
this.levelService.getAll().subscribe(data => this.levels = data.json().response);ОБНОВИТЬ
Оказывается, нет необходимости использовать .json () для HttpClient (на самом деле, я думал о Http, когда писал это) Так что ты можешь просто написать
this.levelService.getAll().subscribe(data => this.levels = data['response']);И, по всей видимости, использование скобок требуется в соответствии с документацией.
Это неправильно. HttpClient больше не требует вызова .json ()
data ['response'] работал хорошо, и теперь я могу видеть свои уровни. Спасибо :)
Я получил это исключение недавно. Все сводилось к тому, что я пытался ngFor над чем-то, что я считал массивом объектов, но на самом деле это не так. Это был единичный объект или примитив.
Я бы порекомендовал отладить это в браузере и убедиться, что levels на самом деле является массивом.
Привет, да, в моем случае это был единственный объект, так как же его разобрать и назначить массиву модели? например массив сотрудников!
Вам нужно добавить в свой сервис метод карты и преобразовать ответ в JSON. измените свой Angular Service на следующее:
@Injectable()
export class LevelService {
constructor(private http: HttpClient) {}
public getAll() {
return this.http.get('http://localhost:8000/api/levels/')
.map(res=>res.json());
}
...
}
Это неверно. HttpClient больше не нуждается в этом дополнительном шаге
Я думаю, что ваши уровни не являются массивом, или у вас есть ошибка при разборе ответа, попробуйте отобразить this.levels