user2120188
user2120188

Reputation: 437

Implementing 'Master - detail' with router (router outlet) in Angular2

I am implementing a Master-Detail screen with Angular2 router. I have a component which defines in its template a list of resources (ul/li formatted): Master part. Each resource in the list is clickable by an "routerLink" binding.

In the same template I have defined an router outlet. The idea is: when I click one of the resources in the list (ul/li), Angular2 should display/render a editable form at the point of the router outlet. I can change the data and press the save button. (Detail part)

When this resource is updated (saved), I want the list of resources (ul/li) to be updated too because may be some data has changed which is also displayed in the list of resources (such as the resource displayname).

Since Angular2 is managing the detail component, I am not declaring the component in my html template. But, because I am not declaring the detail component, I don't have a hook to react on events (like a change event). That is, when my form is succesfully changed, I would emit an "change event". Based upon such an event I could implement a handler at the 'Master part', so that the master can update itself by refreshing the list of resources (ul/li).

The point is: I have lost the relation between master and detail component because of the introduction of the Angular2 router functionality in my app.

Question: Is there a way of solving this pattern?

Upvotes: 0

Views: 1115

Answers (1)

Madhu Ranjan
Madhu Ranjan

Reputation: 17934

Ideal way is to use, Component communication via a service

Also You can try below,

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

@Component({
  selector: 'my-app',
  template: `Angular Route
   <hr />
    <a routerLink="/child1" >Child 1</a>
    <a routerLink="/child2" >Child 2</a>
  <hr />
     Inside Parent component
     <br />
     <br />
     Subscription from child : {{result | json}}
  <hr />
  <div> Child Component</div>
  <br />
  <router-outlet
  (activate)='onActivate($event)'
  (deactivate)='onDeactivate($event)'></router-outlet>
  `
})
export class AppComponent {
  result: any = {};

  constructor(){
  }

  childSubscription: any;

  onActivate($event){
     if(!!$event['parentNotifier']){
       this.childSubscription = $event['parentNotifier'].subscribe(res => {
          this.result = res;
       });
     }
  }

  onDeactivate($event){
    if(!!this.childSubscription){
      this.childSubscription.unsubscribe();
    }
  }
}

@Component({
  selector: 'my-app',
  template: `I am a child
  <button (click)='clickMe()' >Click me to notify parent</button>
  `
})
export class ChildComponent1 {
   @Output() parentNotifier:EventEmitter<any> = new EventEmitter<any>();

   clickMe(){
     this.parentNotifier.next('I am coming from child 1!!');
   }
}

@Component({
  selector: 'my-app',
  template: `I am a child
  <button (click)='clickMe()' >Click me to notify parent</button>
  `
})
export class ChildComponent2 {
   @Output() parentNotifier:EventEmitter<any> = new EventEmitter<any>();

   clickMe(){
     this.parentNotifier.next('I am coming from child 2!!');
   }
}

But notice the name of the event needs to be known by parent somehow like in the sample above i have used it directly parentNotifier.

Here is the Plunker!!

Hope this helps!!

Upvotes: 2

Related Questions