I apologize for bringing up yet another concern regarding Angular 2 view updates, as I have not been able to find a solution in previous discussions. Although I mention the use of NGRX/Store, I highly doubt that it is the reason why the view is not updating correctly. Strangely enough, it seems to update once (at least), but always remains one step behind. The most recent update never seems to take effect. When the model updates, the previous state reflects in the view. It's quite perplexing indeed. Here is the relevant code:
Relevant Installed packages
"@angular/common": "2.0.0-rc.5",
"@angular/compiler": "2.0.0-rc.5",
"@angular/core": "2.0.0-rc.5",
"@angular/forms": "^0.3.0",
"@angular/http": "2.0.0-rc.5",
"@angular/platform-browser": "2.0.0-rc.5",
"@angular/platform-browser-dynamic": "2.0.0-rc.5",
"@angular/router": "^3.0.0-rc.1",
"@angular/upgrade": "2.0.0-rc.5",
"@ngrx/core": "^1.0.1",
"@ngrx/store": "^2.0.1",
My main app module
@NgModule({
imports: [
BrowserModule,
FormsModule,
RouterModule.forRoot(AppRoutes)
],
declarations: [
ConsumerApp,
AppManagement,
MyApps,
AppRegistration,
AppDetails,
],
providers: [
HTTP_PROVIDERS,
STORE_PROVIDERS,
AppManagementService,
],
bootstrap: [
ConsumerApp
]
})
export class AppModule { }
My-Apps Component
@Component({
selector: 'my-apps',
template: require('./templates/my-apps.html')
})
export class MyApps implements OnInit, OnDestroy {
apps = {};
change = 1;
userAppsSubscription;
constructor (
private appsService: AppManagementService,
private store: Store<any> ) {}
ngOnInit () {
this.userAppsSubscription = this.store
.select('userApps')
.subscribe( userApps => {
this.apps = Object.assign(this.apps, userApps);
this.change++;
console.log(this);
})
this.appsService.getUserApps();
}
ngOnDestroy () {
this.userAppsSubscription.unsubscribe();
}
}
My-Apps template
<div id="my-apps">
<h1>My Apps</h1>
<h2>{{change}}</h2>
<p>You currently don't have any registered applications. Click "Register an App" to get started.</p>
<p [hidden]="!loading">{{apps | json}}</p>
<div class="apps-container">
<div class="col-md-4 col-sm-6" *ngFor="let app of apps.available">
<button class="block-button">
<h3>{{app.name}}</h3>
<p><strong>Description:</strong> {{app.description}}</p>
</button>
</div>
</div>
</div>
App Management Service
@Injectable()
export class AppManagementService {
constructor (
private http: Http,
private store: Store<any>) {}
getUserApps () {
this.store
.dispatch({
type: RETRIEVE_USER_APPS,
payload: null
})
return this.http
.get(ALL_APPS)
.toPromise()
.then(response => {
this.store
.dispatch({
type: RECIEVE_USER_APPS,
payload: response.json()
})
})
.catch(response => {
this.store
.dispatch({
type: RETRIEVAL_FAILURE_USER_APPS,
payload: null
})
});
}
}
Upon first encountering the "My Apps" page, this is what ends up being displayed.
https://i.sstatic.net/7XwAo.png
However, this is how the view ultimately appears.
https://i.sstatic.net/vbFCs.png
Isn't it bizarre? You can observe that the page was updated with the second state broadcasted by NGRX/Store, but not with the final state which contains the actual content (the list of 6 apps). Why on earth would the view fail to update correctly?