Best method to set different layout for different pages in angular 4

you can use child e.g.

const appRoutes: Routes = [
    { path: '', component: MainComponent,
        children:{
            { path: 'home'  component:HomeComponent},
            { path: 'about', component: AboutComponent},
            { path: 'contact', component: ContactComponent},
               ..others that share the same footer and header...

        }
    },
    { path: 'login', component: LoginComponent },
    { path: 'register', component: RegisterComponent },
    { path: 'admin', component:AdminComponent, 
         children{
            { path: 'dashboard', component: DashboardComponent },
            { path: 'profile', component: ProfileComponent }
               ..others that share the same footer and header...
         }
    }
    { path: '**', redirectTo: '' }
];

MainComponent and AdminComponent like

<app-header-main></app-header-main>
<router-outlet></router-outlet>
<app-footer-main></app-footer-main>

the post talk about separate in diferent files the routes


You can solve your problem using child routes.

See working demo at https://angular-multi-layout-example.stackblitz.io/ or edit at https://stackblitz.com/edit/angular-multi-layout-example

Set your route like below

const appRoutes: Routes = [
    
    // Site routes goes here 
    { 
        path: '', 
        component: SiteLayoutComponent,
        children: [
          { path: '', component: HomeComponent, pathMatch: 'full'},
          { path: 'about', component: AboutComponent }
        ]
    },
    
    // App routes goes here
    { 
        path: '',
        component: AppLayoutComponent, 
        children: [
          { path: 'dashboard', component: DashboardComponent },
          { path: 'profile', component: ProfileComponent }
        ]
    },

    // no layout routes
    { path: 'login', component: LoginComponent},
    { path: 'register', component: RegisterComponent },
    // otherwise redirect to home
    { path: '**', redirectTo: '' }
];

export const routing = RouterModule.forRoot(appRoutes);

There are cases where the layout and shared elements don't really match the routing structure, or some elements have to be hidden/shown depending on a per-route basis. For such cases I can think of the following strategies (let's take an example of app-header-main component - but it will apply to any shared page element obviously):

Inputs & css classes

You can provide inputs or css classes to control the inner appearance of your shared elements, such as:

  1. <app-header-main [showUserTools]="false"></app-header-main>

or

  1. <app-header-main class="no-user-tools"></app-header-main> and then use :host(.no-user-tools) to show/hide what needs to be

or

  1. at a route level (child or not):

    {
      path: 'home',
      component: HomeComponent,
      data: {
        header: {showUserTools: true},
      },
    },
    

And access it through ActivatedRoute like so: this.route.data.header.showUserTools

TemplateRef input

Inside app-header-main component:

@Input() rightSide: TemplateRef<any>;

Input of type TemplateRef<any> where you could feed an ng-template element directly

<app-header-main [rightSide]="rightside"></app-header-main>
<ng-template #rightside>your content here</ng-template>

Named slot transclusion

You can author the app-header-main so that it uses named slot transclusion

Inside of app-header-main template:

<ng-content select="[rightSide]"><ng-content>

Usage:

<app-header-main class="no-user-tools">
  <div rightSide>your content here</div>
</app-header-main>