Reputation: 177
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.
Upvotes: 7
Views: 2000
Reputation: 1
As you want to display the same/different details within two different layouts:
Upvotes: 0
Reputation: 15098
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
Upvotes: 3
Reputation: 7396
You can achieve that in a few steps:
ng generate service data-passing
import {Injectable} from '@angular/core';
@Injectable({
providedIn: 'root',
})
export class DataPassingService {
public firstComponentData;
public secondComponentData;
constructor() { }
}
import {DataPassingService} from '...';
...
constructor(public dataPassingService: DataPassingService) {
}
setDate(first, second) {
this.dataPassingService.firstComponentData = first;
this.dataPassingService.secondComponentData = second;
}
*ngIf
as you used before to control components visibility:<div *ngIf="layout1" class="layout1">
<div class="sidebar-layout1">
some items
</div>
<child-component [something]="dataPassingService.firstComponentData"></child-component>
</div>
<div *ngIf="!layout1" class="layout2">
<child-component [something]="dataPassingService.secondComponentData">
<p>some content...</p>
</child-component>
</div>
Upvotes: 0
Reputation: 28701
Use [hidden] attribute instead with the reverse logic, it will prevent the element destroying.
<div [hidden]="!layout1" class="layout1">
...
</div>
<div [hidden]="layout1" class="layout2">
...
</div>
I hidden just hides/shows the DOM element with css by changing display style
Upvotes: 0