Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 6 - Multiple child components should be of same instance

I simplified my problem:

<div *ngIf="layout1" class="layout1">
  <div class="sidebar-layout1">
     some items
  </div>
  <child-component [something]="sth"></child-component>
</div>
<div *ngIf="!layout1" class="layout2">
  <child-component [something]="sth">
    <p>some content...</p>
  </child-component>
</div>

I have a parent component which has the possibility of a normal layout (layout1) and a fullscreen layout(layout2) (In fullscreen mode the child-component should be in fullscreen). The problem is, when i change layout with *ngIf, the child-component is destroyed and a new one is generated. I want to have the same instance and don't loose important informations of child-component and avoid some api calls.

Is there any way to achive that the child-component will not be destroyed or is there a better way than ngIf?

I just need one instance of child-component for different layouts in a parent-component.

like image 309
stoph Avatar asked Jun 26 '18 07:06

stoph


1 Answers

As you may have noted, If you hide elements using *ngIf then a new component is created. This is what we will try to focus on and try to avoid creating a new component.

For this, we can use a 'switcher layout' and pass the child component as content

<app-layout-switcher [layout1]="layout1">
  <ng-container>
    <child-component
      *ngIf="sth$ | async as sth; else loading"
      [something]="sth"
    >
      <p>some content...</p>
    </child-component>
    <ng-template #loading>
      <h1>Loading...</h1>
    </ng-template>
  </ng-container>
</app-layout-switcher>

I have added a mock http call to show the loading.

In our app-layout-switcher component we can switch between the layout as desired. We will pass the child-component into a template to be able to reuse it in the layout

<div *ngIf="layout1">
  <app-layout-1>
    <ng-template [ngTemplateOutlet]="childComponent"></ng-template>
  </app-layout-1>
</div>

<div *ngIf="!layout1">
  <app-layout-2>
    <ng-template [ngTemplateOutlet]="childComponent"></ng-template>
  </app-layout-2>
</div>

<ng-template #childComponent>
  <ng-content></ng-content>
</ng-template>

Now we can use the template in our layouts

<header>
  <h1>Layout 1</h1>
</header>
<main>
  Contents in Layout 1
  <div>
    <ng-content></ng-content>
  </div>
</main>

<footer>Layout 1 Footer</footer>

We are now using only one instance of the component. To confirm this I have added a textfield in the demo. You will notice that data is persisted when switching the layout

See this Demo

like image 136
Owen Kelvin Avatar answered Oct 08 '22 15:10

Owen Kelvin