1

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.

4
  • Where do you emit the events? How is socket involved? I assume the problem is caused by the socket API not being patched by zone. Commented Jun 30, 2016 at 11:20
  • I updated answer, and renamed title. At first I wanted to ask about sockets, but I realized that it's happening for angular events as well. Commented Jun 30, 2016 at 11:26
  • I still can't see how socket is involved. Where is selectSport called from? Commented Jun 30, 2016 at 11:26
  • This is not socket related, I updated question both title and body. Commented Jun 30, 2016 at 11:37

1 Answer 1

1

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);})

Sign up to request clarification or add additional context in comments.

2 Comments

Unfortunately no, view is not changed :/
I assume you are running in dev mode and might be getting an error from angular. If so let me know. I think it would be great if you can show piece of your template as well

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.