进行HTTP调用以从嵌套组件获取值时,未填充下拉列表

时间:2018-11-07 01:06:59

标签: angular

我有一个组件,该组件使用服务从API获取数据。该服务和组件可以正常工作,因为我可以在表格的页面上成功显示此数据。我现在尝试在另一个组件内部使用此组件来填充下拉表单控件。不幸的是,此下拉列表并未填充。

调试时,这看起来像是一个异步问题,因为我可以看到控制台中正在显示数据(使用console.log()进行调试)。我还可以看到在显示之前和之后放置的其他console.log()语句,但是都在调用嵌套组件之前在之前输出它们的值。

呼叫组件

ngOnInit() {
    // Debugging code
    console.log('Before this.playerComponent.getPlayers()');

    // Nested component that gets the data from a service
    this.playerComponent.getPlayers();
    this.players = this.playerComponent.players;

    // Debugging code
    console.log('After this.playerComponent.getPlayers()');
}

PlayerComponent(嵌套组件)

getPlayers(): void {
    this.playerService.getPlayers().subscribe(
        players => {
            this.players = players;
        },
        error => this.errorMessage = <any>error
    );
}

playerService

getPlayers(): Observable<IPlayer[]> {
    return this.http.get<IPlayer[]>(`${this.url}/players`).pipe(
        tap(data => console.log(JSON.stringify(data))),
        catchError(this.handleError)
    );
}

HTML组件

<div class="form-group">
    <label for="player">Player</label>
    <select id="player" #season class="custom-select" formControlName="playerid">
        <option value="" disabled selected>Select Player (required)</option>
        <option *ngFor='let player of players' value="{{player.playerid}}">{{player.player}}</option>
    </select>
</div>

以下是屏幕截图,显示了带有我的调试输出的控制台:

enter image description here

所以我的问题是,我是否需要更改此代码以等到HTTP请求返回数据之后?还是我需要更改代码,以便在返回数据时做出反应?

3 个答案:

答案 0 :(得分:1)

组件之间很难管理数据。如今,使用Angular,从 Presentation Component 中分离 Smart Component 是一个好习惯。

基本上,智能组件负责管理数据并将其传送到演示组件,其中演示组件仅负责显示数据。

这是关于主题的很好的解释。

示例:

呼叫组件(将成为我们的智能组件)

players = null;

constructor(private playerService: PlayerService) {}

ngOnInit() {
    this.playerService.getPlayers().subscribe(players => this.players = players);
}

调用组件HTML

<app-players [players]="players"></app-players>

播放器组件(演示组件)

@Input() players;

播放器组件HTML

<div class="form-group">
<label for="player">Player</label>
<select id="player" #season class="custom-select" formControlName="playerid">
    <option value="" disabled selected>Select Player (required)</option>
    <option *ngFor='let player of players' value="{{player.playerid}}">{{player.player}}</option>
</select>
</div>

遵循这种做法(将数据从父组件倾泻到子组件)使工作变得更加轻松。

答案 1 :(得分:0)

为什么以这种方式编码,您应该仅在一个组件中拥有模型,并且如果希望子级的数据在父级使用事件发射器上可用,则子级可以在其自己的ngOnInit方法中执行该模型,以通知父级有关可用性的信息一旦服务返回响应,就会从子对象中提取玩家数组,然后通过eventemitter的通知重新初始化父组件的数组。

答案 2 :(得分:0)

您可以获取Observable而不是访问实例变量。异步调用完成后,它将始终确保您拥有数据。

进行以下更改

PlayerComponent(嵌套组件)

getPlayers(): void {
    return this.playerService.getPlayers(); //<-- return players Observable 
}

呼叫组件

ngOnInit() {
    // Debugging code
    console.log('Before this.playerComponent.getPlayers()');

    // Nested component that gets the data from a service
    this.playerComponent.getPlayers().subscribe(
    players =>  this.players = players);
}

如果您还希望嵌套组件中的播放器,则可以使用相同的函数getPlayers()并进行订阅。

  

注意:由于代码是直接在stackoverflow编辑器中编写的,因此可能存在一些拼写错误或语法错误。请纠正自己。