1

Look code.

import {Component} from 'angular2/core';
import {App} from 'client/project/project.app';
import {ProjectService} from 'service/project.service';

@Component({
    selector: 'project-info',
    templateUrl: 'client/project/info/project-info.html'
})
export class ProjectInfoComponent {
    project:IProject;

    constructor(
        private app: App,
        private projectService: ProjectService
    ){         
      this.project = this.app.selectedProject;
    }
}

I change this.app.selectedProject={...} in other component, I would like to this component rerender. How to do it? Invented only if using EventEmitter.

this.app.selectedProject.subscribe(project => {
 this.project = project;
});
GrKoV
  • 31
  • 1
  • 2

3 Answers3

1

I don't know if this is the best practice or not, but I don't like change detection and prefer to work with events, so, this is how I deal with similar cases:

First of all, keep in mind, that data flows downwards, event flow upwards (considering that parent is on top). In other words, when you want to change data, change it in parent, and child will auto update, and to do this you have to send an even to the parent.

  1. Now to do that, in the child, we should define @Output() eventToSend: EventEmitter = new EventEmitter(); and we trigger it by using this.eventToSend.next(params);
  2. In the parent we have to listen to the event, one way to do is inside the template, you can add (eventToSend)="eventListen($event)" and in your ts file you can just define eventListen(params) and do whatever you please.

I hope this is what you are looking for.

Labib Ismaiel
  • 1,240
  • 2
  • 11
  • 21
1

If in the "other component" you really are assigning a different object to the service's selectedProject property, then the ProjectInfoComponent will never know... it's project property will still have a reference to (point to) the original/previous selected project object that was set in the constructor.

If ProjectInfoComponent's project property needs to be notified whenever the selected project changes, use a Subject or an Observable. The cookbook has a good example of how how to use Subjects and Observables: bi-directional service.

If you don't need to be notified (i.e., you don't need to execute any component logic/code when the selected project changes), a simpler solution would be to bind to the service property rather than create your own project reference (which can get out of synch). E.g., in ProjectInfoComponent's template, use something like {{app.selectedProject.somePropertyHere}}. Now, whenever the service's selectedProject property changes, the view will update.

Mark Rajcok
  • 362,217
  • 114
  • 495
  • 492
0

In fact, it depends on the way you update the this.app.selectedProject. Angular2 only detects by default when the whole reference changes not when elements in the object are updated.

// For example updating the name of selectedProject. This won't
// refresh the component view
this.app.selectedProject.name = 'some name';

// For example updating the name of selectedProject. This will
// refresh the component view
this.project = { name: 'some name' };

If you really want to detect changes into the object you reference. You need to leverage the DoCheck interface and the KeyValueDiffers class to implement a custom checking. Here is a sample:

@Component({
  selector: 'project-info',
  (...)
}) 
export class ProjectInfoComponent implements DoCheck {
  project: IProject;
  differ: any;

  constructor(differs:  KeyValueDiffers) {
    this.differ = differs.find([]).create(null);
  }

  ngDoCheck() {
    var changes = this.differ.diff(this.myObject);

    if (changes) {
      changes.forEachChangedItem((elt) => {
        // elt.key tells which property in the object was updated
      }
    });
  }
}

See this question for more details:

Community
  • 1
  • 1
Thierry Templier
  • 198,364
  • 44
  • 396
  • 360