我正在进行API调用并存储一堆用户配置文件,我希望能够为每个配置文件动态创建卡片(Angular Material Design md-card)。返回的配置文件数量可能不同,因此需要是动态的。
这是我的组件文件,它生成JSONP请求并将配置文件存储在profiles
变量中:
import {Component, Injectable, OnInit} from '@angular/core';
import {Jsonp} from '@angular/http';
@Component({
selector: 'app-staff',
templateUrl: './staff.component.html',
styleUrls: ['./staff.component.css']
})
@Injectable()
export class StaffComponent implements OnInit {
public searchField: string;
apiRoot = 'this/is/my/api/url';
public results: JSON;
public profiles;
constructor(private jsonp: Jsonp) {
}
ngOnInit() {
}
setSearchField(field: string){ // ignore this method
this.searchField = field;
console.log('Received field: ' + this.searchField);
}
search(term: string) {
const apiUrl = `${this.apiRoot}?search=${term}&rows=10&callback=JSONP_CALLBACK`;
return this.jsonp.request(apiUrl).map(results => { this.results = results.json(); console.log(this.results['profiles'][0]); this.profiles = results['profiles']; return results.json(); });
}
}
这是上述组件的模板,我正在尝试使用*ngFor
创建md-card
列表:
<div class="container-fluid">
<div class="row justify-content-center">
<div class="col-md-auto">
<ul>
<li *ngFor="let profile of profiles">
<md-card class="example-card">
<md-card-header>
<div md-card-avatar class="example-header-image"></div>
<md-card-title>{{profile.fullName}}</md-card-title>
<md-card-subtitle>Department</md-card-subtitle>
</md-card-header>
<img md-card-image src="../assets/image.png">
<md-card-content>
<p>
This section of the card will contain information about the result being searched for. It could also be
accompanied by additional information such as links.
</p>
</md-card-content>
<md-card-actions>
<button md-button>APPLY</button>
<button md-button>GO TO xyz</button>
</md-card-actions>
</md-card>
</li>
</ul>
</div>
</div>
</div>
我的个人资料数据采用数组的形式(假设数组的长度不超过10)并采用以下形式:
0: {fullName: "Foo Bar", emailAddress: "foobar@foobar.com", image: "/profile/image/foobar/foobar.jpg", phoneNumber: "99999999"},
1: {fullName: "Foo Bar1", emailAddress: "foobar1@foobar.com", image: "/profile/image/foobar1/foobar1.jpg", phoneNumber: "919999999"}
但是,没有md-card
被渲染。我检查过profiles
不是空的。如何根据配置文件的数量动态创建卡片,并使用配置文件对象中的值填充内容?
答案 0 :(得分:4)
您可以尝试使用BehaviorSubject
中的rxjs
并从响应中发出配置文件。在您的模板中使用async
管道。这样可以确保角度的变化检测能够发现变化。
private readonly profiles$$ = new BehaviorSubject([]);
public readonly profiles$ = this.profiles$$.asObservable();
// ...
search(term: string) {
const apiUrl = `${this.apiRoot}?search=${term}&rows=10&callback=JSONP_CALLBACK`;
return this.jsonp.request(apiUrl).map(res => {
let results = res.json();
this.profiles$$.next(results.profiles);
return results;
});
}
并在您的模板中:
<li *ngFor="let profile of profiles$ | async">
<!-- ... -->
</li>
顺便说一下:从组件中删除@Injectable
装饰器,组件不应该是injectable
。
注意:您应该考虑将api调用移动到共享服务中,这样可以保持组件的逻辑清洁,并且您也可以在其他组件中使用它。您也可以了解redux
&#34;模式&#34;,为此您可以查看@ngrx/store
和@ngrx/effects
。更多信息可以在@ngrx/platform monorepo找到。它可以让您对应用程序的状态拥有巨大的控制权,并且可以更轻松地管理数据并控制来自外部API的请求/响应。
答案 1 :(得分:0)
您的结果将被处理为map()并仍然返回Observable|promise
因此您需要处理来自服务器的值的async
行为。
Angular提供了一个async
管道,您可以在模板中使用该管道来说明数据何时会在我的UI中反映出来。
您可以将服务器调用移动到@Injectable()
服务,该服务将返回Observable并将其存储在组件变量中,然后在您的UI中,您可以简单地使用async
pipe
<ul>
<li *ngFor="let profile of profiles | async">
<md-card class="example-card">
<md-card-header>
这与angular api中的Observable和http调用完美配合。当您的角度加载时,它完成模板绑定,但服务器的数据在此之后,这就是您的数据不会反映在UI中的原因。所以你必须处理这种异步行为。希望这会有所帮助:)