I want to make several different module layouts
For example, I made one separate layout and named it user. Now, I have two layouts, one main, root layout and user layout.
In the main layout, I made a button that leads to the user component. And in the user layout, I made a button that leads to the main component.
The task before me is to make it so that when the button is pressed, the component from which I leave disappears. What I mean is that if I'm in the main root component and I press the "user" button which leads to the /user page, then after clicking I should go to the /user page and the main component should disappear. Or if I am in the /user component and press the "home" button that leads to the /home page, then after clicking I should go to the main /home and the /user component should disappear.
I implemented this using a service.
After I did, I noticed that if I go to the /user page and try to refresh it, then at some point, for a fraction of a second, I notice the main component. He appears and disappears. This happens very quickly and at the same time - it is very noticeable. It worries me, I don't know how to get rid of this defect. Please tell me how to get rid of this problem?
AppComponent
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnDestroy {
show: boolean = true;
subscription: Subscription;
constructor(private showContentService: ShowContentService) {
this.subscription = showContentService.contentHome.subscribe(value => {
this.show = value;
});
}
hideContent() {
this.show = false;
}
ngOnDestroy() {
// Prevent memory leak when component is destroyed
this.subscription.unsubscribe();
}
}
app.component.html
<ng-container *ngIf="show">
<p>Main page</p>
<button (click)="hideContent()" routerLink="/user">User</button>
</ng-container>
<router-outlet></router-outlet>
AppRoutingModule
const routes: Routes = [
{ path: 'user', loadChildren: () => import('./user/user.module').then(m => m.UserModule) }
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
ShowContentService
@Injectable({
providedIn: 'root'
})
export class ShowContentService {
// Observable string sources
private showContent = new Subject<boolean>();
// Observable String Streams
contentHome = this.showContent.asObservable();
showContentHome(showContent: boolean) {
this.showContent.next(showContent);
}
}
UserComponent
export class UserComponent {
constructor(private showContentService: ShowContentService) {
this.showContentService.showContentHome(false);
}
showContentHome() {
this.showContentService.showContentHome(true);
}
ngOnInit(): void {
}
}
user.component.html
<p>User page</p>
<button (click)="showContentHome()" routerLink="/">Home</button>
UserRoutingModule
const routes: Routes = [
{ path: '', component: UserComponent }
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class UserRoutingModule { }
CodePudding user response:
A possible solution is to use multiple <router-outlet>
elements. You can have a router outlet for each module.
The way I would structure it is to have your main app
be just a router-outlet element in the template. I would then create two separate modules, one for main
, and one for user
. Each of these modules would contain their own router outlet and their own layout components which would render in the root apps router outlet.
app-routing.module.ts
const routes: Routes = [
{
path: '',
loadChildren: () => import('./main/main.module').then((m) => m.MainModule),
},
{
path: 'user',
loadChildren: () => import('./user/user.module').then((m) => m.UserModule),
},
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule],
})
export class AppRoutingModule {}
app.component.html
<router-outlet></router-outlet>
main-routing.module.ts
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { MainLayoutComponent } from './containers/main-layout/main-layout.component';
import { MainPageComponent } from './pages/main-page/main-page.component';
const routes: Routes = [
{
path: '',
// This layout component will render in app's router-outlet
component: MainLayoutComponent,
children: [
{
path: '',
// This page component will render in mains router-outlet
component: MainPageComponent,
},
],
},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class MainRoutingModule {}
main-layout.component.html
<h1>Main Layout</h1>
<router-outlet></router-outlet>
user-routing.module.ts
const routes: Routes = [
{
path: '',
// This layout component will render in apps router-outlet
component: UserLayoutComponent,
children: [
{
path: '',
// This child component will render in users router-outlet
component: UserPageComponent,
},
],
},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class UserRoutingModule {}
user-layout.component.html
<h1>User Layout</h1>
<router-outlet></router-outlet>
I mocked up a stackblitz that demonstrates the solution.