Home > Enterprise >  Multi layout Angular
Multi layout Angular

Time:07-31

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 { }

enter image description here

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.

https://stackblitz.com/edit/angular-ivy-oy44ja

  • Related