简体   繁体   中英

Angular 2 view not updating after model change

Can't get my view to update even though my model clearly is updated. Tried using NgZone but it doesn't help.

I'm injecting RouteService in two components: app.component and start-page-list.component. RoutService is using Subject to pass data between components:

import { Injectable } from '@angular/core';
import { Round } from "app/round";
import { Subject } from "rxjs/Subject";

@Injectable()
export class RoundService {

  private roundSource = new Subject<Round>();

  roundItem$ = this.roundSource.asObservable();

  changeRound(value:Round) {
    this.roundSource.next(value);
  }
}

app.components view gets updated as expected but start-page-list.component does not.

app.component:

import { Component } from '@angular/core';
import { Http } from "@angular/http";
import 'rxjs/add/operator/toPromise';
import { RoundService } from "app/round.service";
import { Round } from "app/round";

@Component({
  selector: 'app-root',
  template: `
  <div class="container">
  <div class="page-header">
    <h1>{{currentRound.id}}</h1>
  </div>  
  </div>
  <router-outlet></router-outlet>
  `,
  styleUrls: []
})
export class AppComponent {
  currentRound: Round = {id:0,name:"No round set yet"};

  constructor(private http: Http, private round : RoundService) { }

  callBackFunc(data:Round) {
    this.currentRound = data;
  }

  ngOnInit() {
    this.round.roundItem$.subscribe(
      (data:Round) => this.callBackFunc(data)
    );
  }  
}

Here currentRound.id is updated!

start-page-list.component (rendered at the router-outlet in app.component):

import { Component, OnInit, Input, NgZone } from '@angular/core';
import { PlayerService } from "app/player.service";
import { Game } from "app/game";
import { Player } from "app/player";
import { GameService } from "app/game.service";
import { RoundService } from "app/round.service";
import { Round } from "app/round";
import 'rxjs/add/operator/toPromise';

@Component({
  selector: 'app-start-page-list',
  template: `{{currentGameset.id}}`,
  styleUrls: []
})
export class StartPageListComponent implements OnInit {

  currentGameset:Round = {id:0,name:'No round set yet'};

  constructor(private gameService: GameService, private roundService: RoundService, private zone: NgZone) { }

  callbackFunc(data:Round) {
    this.currentGameset = data;
    console.log("currentGameset.id= " + this.currentGameset.id);
  }

  ngOnInit() {
    this.roundService.roundItem$.subscribe(
      (data:Round) => this.zone.run( () => this.callbackFunc(data) )
    );
  }  

}

Here currentGameset.id is not updated even though the model is (console log shows updated value). As you can see I've tried using NgZone.

Any suggestions what might be wrong here?

Edit If i put the start-page-list.component as a child component to the app.component i don't get the problem. Then the view gets updated as I expect. The problem seems to be only when I use the router-outlet rendering of the component.

When you do currentGameset = data , you're breaking what the template was referring to. You would think that it will continue to refer to the currentGameset but that's not how it works!

Try to add a wrapper for currentGameset like:

gameSetParent = { 
  currentGameset: {id:0,name:'No round set yet'};
}

In callback func,

this.gameSetParent.currentGameset = data;

You need to update the template to reflect the change.

Turned out that using BehaviorSubject instead of Subject in the service was the solution!

Anyone care to explain why?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM