2017-09-05 64 views
9

我正在进行API调用并存储一堆用户配置文件,我希望能够为每个配置文件动态创建卡(Angular Material Design md卡)。返回的配置文件数量可能会有所不同,因此这需要动态。从API响应动态创建md卡

这是我的组件文件,这使得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: "[email protected]", image: "/profile/image/foobar/foobar.jpg", phoneNumber: "99999999"}, 

1: {fullName: "Foo Bar1", emailAddress: "[email protected]", image: "/profile/image/foobar1/foobar1.jpg", phoneNumber: "919999999"} 

但是,没有md-card正在呈现。我检查了profiles不是空的。如何根据配置文件的数量动态创建卡片,并使用配置文件对象中的值填充内容?

+0

你的'个人资料'数据是怎么样的?出租车你添加到你的问题? – Faisal

+0

@Faisal我在我的问题中添加了更多关于'profiles'数据的信息。 – bawse

+0

'this.profiles = results ['profiles']'应该是'this.profiles = this.results ['profiles']'或'this.profiles = results.json()['profiles']' – cyrix

回答

5

您可以尝试使用rxjs中的BehaviorSubject并从响应中发出配置文件。在你的模板中使用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> 

BTW:从组件中移除的@Injectable装饰,组件不应该injectable

注意:您应该真的考虑将api调用移动到共享服务中,这样可以保持组件的逻辑清洁,并且也可以在其他组件中使用它。您也可以通知自己关于redux“模式”,您可以查看@ngrx/store@ngrx/effects。更多信息可在@ngrx/platform monorepo找到。它将使您对应用程序状态有很大的控制,并且更容易管理您的数据并控制来自外部API的请求/响应。

+0

感谢您的回答,我已经尝试了您的方法,但我在控制台中出现错误。 '不能绑定'ngForOr',因为它不是'li'.'的已知属性。请告知如何从这里开始。我也从组件中删除了Injectable装饰器,这是一个错误。 – bawse

+0

我认为你的意思是'ngForOf',因为它不是'li''的已知属性,你是否在包含该组件的模块中从'@ angular/common'中导入CommonModule? – cyrix

+0

不,控制台错误清楚地说明了'ngForOr'。我已经导入了'CommonModule'。你有能力提供一名运动员吗?我最初遵循本教程设置我的角度服务,所以请随时使用这里使用的API:https://codecraft.tv/courses/angular/http/jsonp-with-observables/ – bawse

0

将结果处理成map()并仍然返回Observable|promise因此,您需要处理来自服务器的值的async行为。

Angular提供了一个async管道,您可以在您的模板中使用该管道,以便在数据将在我的用户界面中反映出来。

您可以将您的服务器呼叫转移到一个@Injectable()服务将返回观察到的,存储在您的组件变量,然后在你的用户界面,你可以简单的使用async

<ul> 
    <li *ngFor="let profile of profiles | async"> 
     <md-card class="example-card"> 
     <md-card-header> 

这与观察到的,完美的作品HTTP调用角度api。当你的角度加载时,它完成了模板绑定,但服务器的数据来自这之后,这就是为什么你的数据不反映在用户界面。所以你必须处理异步行为。希望这有助于:)

+0

这不起作用,因为他在'map'调用中设置'profiles' 。因此'profiles'不是可观察的。 – cyrix

+1

他正在使用个人资料!我以为他在用结果。我会改变我的答案,指向结果,以便它能够工作 –

+1

不幸的是,他正在组件内部执行api调用,并将结果应用到'map'中,这有助于导致角度变化检测无法接受变化。但是如果'profile'像我的意思那样是可观察的,你的回答是正确的。 – cyrix