user2180794
user2180794

Reputation: 1455

Angular2 - How to destroy child component when user navigates to another component

I have a header component and a sidebar component as child component of Main component as follows.

main component

@Component({
    selector: 'my-app',
  template: `
    <body>    
      <app-header></app-header>
      <app-sidebar></app-sidebar>
      <main class="mdl-layout__content mdl-color--grey-100">         
         <auth-router-outlet></auth-router-outlet>        
      </main>
    </div>         
  </body>

    `,
    directives: [ROUTER_DIRECTIVES, SidebarComponent, HeaderComponent, MDL, AuthRouterOutlet,SimpleNotificationsComponent],
    providers: [AUTH_PROVIDERS,NotificationsService]
})

export class AppComponent {}

The header component has a child component. I want to destroy this child component when the user click on any of the sidebar links. Currently the child component becomes part of the header once data is rendered and breaks the layout.

HeaderComponent

@Component({
    selector: 'app-header',
     directives: [AptSearchComponent],
    template: `
            <div class="mdl-textfield__expandable-holder">
              <input class="mdl-textfield__input" type="text" id="search" (keyup.enter)="Search($event)">
            </div>       
     <aptsearch *ngIf="apartment" [model]="apartment"></aptsearch>    
    `,
})

export class HeaderComponent {

  public apartment: string;

    constructor(private apartmentService: ApartmentService,private router: Router,private sharedService: SharedService) { 
       this.apartmentService=apartmentService;
       this.sharedService=sharedService;
     }

     Search(event){  
       this.apartment = event.target.value;
       this.router.navigate(['AptSearch']);     
     }
}

child component of the header component, which needs to be destroyed when user click on any links from the sidebar.

@Component({
    selector: 'aptsearch',  
  template: `    
     <div *ngFor="#aptdetails of aptDetails">
                <h2 class="mdl-card__title-text">{{aptdetails.aptID}}</h2>
              </div>

    </div>         
    `,
    directives: [ROUTER_DIRECTIVES]
})

export class AptSearchComponent implements OnInit {
    @Input() model:string;

    aptDetails: any;

    constructor(private apartmentService: ApartmentService, private sharedService: SharedService,private zone:NgZone) {
    this.apartmentService = apartmentService;        
    }


    ngOnInit(){}

    ngOnChanges(changes: any) {
    console.log('Inside the Search Component from parent -->' +this.model);
    this.apartmentService.searchApt2(this.model).subscribe(res => {this.aptDetails = res});
    }    
}

How can this be achieved ?

Upvotes: 2

Views: 8789

Answers (2)

Carlos Mermingas
Carlos Mermingas

Reputation: 3892

There's no straightforward way to connect two sibling components (header and sidebar, in your case).

One option would be to have the sidebar component emit an event (EventEmitter) that the app component (a) subscribes to and (b) then sets a property in the header component.

Another option, my preferred one, would be to have an observable in your ApartmentService or another service. Something like this:

In ApartmentService:

apartmentSearch: new BehaviorSubject<string>();

search(query: string) {
    this.apartmentSearch.next(query);
}

In Sidebar when something is clicked, call search with null:

somethingClicked() {
    this.apartmentService.search(null);
}

In Header:

ngOnInit() {
    this.subscription = this.apartmentService.apartmentSearch.subscribe(x => this.apartment = x);
}

ngOnDestroy() {
    this.subscription.unsubscribe();        
}

Search(event) {
    this.apartmentService.search(event.target.value);
}

I hope this helps.

Upvotes: 0

G&#252;nter Z&#246;chbauer
G&#252;nter Z&#246;chbauer

Reputation: 657396

Use *ngIf

and set showChild to false to get the element removed from the DOM.

Upvotes: 1

Related Questions