Ned
Ned

Reputation: 4141

Change component on received event - angular2

I have a problem with notifying component, that changes occurred.

Let's say I have one component A, that emits event E (through some service). Component B is subscribed to that event. If I console.log received event and property of component B, I do see that it is changed.

However, component's template remains the same.

I figured that if I use ChangeDetectorRef, and changeDetectorRef.detectChanges(), view is refreshed. But I keep getting following error:

Attempt to use a destroyed view: detectChanges.

Is this desired way to use and notify component? Is there something better?

Here's a brief example of code I'm using:

this is component B, that should be changed

import {Component, OnInit, ChangeDetectorRef} from '@angular/core';

import {LiveIndexService} from './services/live-index.service';
import {LiveNavigationService} from '../../services/live-navigation.service';

@Component({
  selector: 'live-index',
  template: require('./index.html'),
  providers: [BetradarService]
})
@CanActivate(() => {
  return areDependenciesFetched();
})
export class LiveIndexComponent implements OnInit {

constructor(
  private _liveNavigationService: LiveNavigationService,
  private _changeDetector: ChangeDetectorRef) {}

public ngOnInit() {
  this._liveNavigationService.sportSelectedEvent$.subscribe(selectedSport => {
  this._selectedSport = selectedSport;
  console.log(this._selectedSport); // I see it is changed, but if I omit next line, it's not working.
  this._changeDetector.detectChanges();
});

} }

this is component A that triggers service which emits event

import {Component, Output, EventEmitter, ChangeDetectorRef} from 'angular2/core';
import {LiveNavigationService} from '../../services/live-navigation.service';

@Component({
   selector: 'live-breadcrumbs',
   template: require('./live-breadcrumbs.html')
})
export class LiveBreadcrumbsComponent {

   private _selectedSport;

   public constructor(private _liveNavigationService: LiveNavigationService,
                 private _changeDetectorRef: ChangeDetectorRef) {}

   // this function is triggered from template (onClick)
   private _selectSport(sport) {
     this._selectedSport = sport;

     this._router.navigate(['Index']); // this will navigate to component B

     this._liveNavigationService.selectSport(sport);
  }
}         

I emit object from service like this:

import {Injectable, EventEmitter} from '@angular/core';

@Injectable()
export class LiveNavigationService {

   public sportSelectedEvent$: EventEmitter<any> = new EventEmitter<any>();

   public selectSport(sport) {
      this.sportSelectedEvent$.emit(sport);
   }
}

this is html

<div id="breadcrumb">
  <div class="dropdown">
    <div class="wrapper">
        <a class="name">{{ _selectedSport ? _selectedSport.name : 'Sport'}}</a>
        <div class="icon"><span></span></div>
    </div>
    <div class="list">
        <div class="title">Sports</div>
        <div class="list-item" [ngClass]="{selected: sport == _selectedSport}" (click)="_selectSport(sport)" *ngFor="let sport of _sportsWithMatches">{{ sport.name }}</div>
    </div>
</div>

I'm still on RC1.

Upvotes: 1

Views: 354

Answers (1)

Arpit Agarwal
Arpit Agarwal

Reputation: 4003

I don't think you should be using changeDetectorRef. As change detection strategy is not set to onpush.
I think if you move emit logic to after navigation is complete then you code will work. If you are using rc1 router

this._router.navigate(['Index']).then( ()=>this._liveNavigationService.selectSport(sport);)

For 3.0.0 router you can do

this._router.events.subscribe( e => { if(e instance of NavigationEnd && this.router.url == 'index') this._liveNavigationService.selectSport(sport);})

Upvotes: 1

Related Questions