Angular How to change navmenu header based on route

試著忘記壹切 提交于 2019-12-10 14:17:51

问题


I am working on a Dashboard layout in my current project with Angular 4+.

When the user navigates between the different sections of the app I need the navmenu header title to update to reflect the current section of the app.

As an example when the user visits settings "Page Title" should change to "Settings"

The project is based on the .net core 2 Angular template Below is the code I have to makeup the app routing as well as the dashboard routing.

navigation.service

import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';

@Injectable()
export class NavigationService {
    private titleSource = new BehaviorSubject<string>("Page Title");
    currentTitle = this.titleSource.asObservable();

    constructor() {
    }

    changeTitle(title: string) {
        this.titleSource.next(title);
    }
}

app-routing.module

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';

import { HomeComponent } from "./components/home/home.component";

const appRoutes: Routes = [
    { path: '', redirectTo: 'home', pathMatch: 'full' },
    { path: 'home', component: HomeComponent },
    { path: '**', redirectTo: 'home' }
]

@NgModule({
    imports: [
        RouterModule.forRoot(appRoutes)],
    exports: [RouterModule]
})
export class AppRoutingModule { }

app.module.shared

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';

import { AppRoutingModule } from './app-routing.module';
import { DashboardModule } from "./components/dashboard/dashboard.module";

import { UtilsModule } from "./components/shared/shared.module";
//app components
import { AppComponent } from './components/app/app.component';

import { NavigationService } from "./services/navigation.service";

@NgModule({
    declarations: [
        AppComponent,

    ],
    imports: [
        SharedModule,
        DashboardModule,
        AppRoutingModule,
        DevExtremeModule,
        CommonModule,
        HttpModule,
        FormsModule
    ],
    providers: [NavigationService]
})
export class AppModuleShared {
}

dashboard-routing.module

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';

import { DashboardComponent } from "./dashboard.component";
import { SettingsProfileComponent } from "./settings/settingsProfile/settings.profile.component";
import { SettingsEmailComponent } from "./settings/settingsEmail/settings.email.component";
import { UsersListComponent } from "./users/users.list.component";

export const dashboardRoutes: Routes = [
    {
        path: 'dashboard',
        component: DashboardComponent,
        children: [{
            path: 'settings',
            data: { title: 'Settings' },

            children: [{
                path: 'profile',
                component: SettingsProfileComponent
            },
            {
                path: 'email',
                component: SettingsEmailComponent
            }]
        }, {
                path: 'users',
                data: { title: 'Users' },
                children: [{
                    path: '',
                    component: UsersListComponent
                }]
        }]
    }
];

@NgModule({
    imports: [
        RouterModule.forChild(dashboardRoutes)
    ],
    exports: [RouterModule]
})
export class DashboardRoutingModule { }

dashboard.module

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { UtilsModule } from "../shared/shared.module";

import { DashboardRoutingModule } from "./dashboard-routing.module";

import { DashboardComponent } from './dashboard.component';
import { SettingsProfileComponent } from "./settings/settingsProfile/settings.profile.component";
import { SettingsEmailComponent } from "./settings/settingsEmail/settings.email.component";
import { UsersListComponent } from "./users/users.list.component";

@NgModule({
    imports: [
        CommonModule,
        UtilsModule,
        DashboardRoutingModule
    ],
    declarations: [
        DashboardComponent,
        SettingsProfileComponent,
        SettingsEmailComponent,
        UsersListComponent,
    ],
    providers: []
})
export class DashboardModule {
}

I am trying to avoid having a OnInit in each component. Is it possible to do this only in the routing? The project is early on so if there are any other recommendations on how to accomplish this we are open to change.


回答1:


Another option may be a route guard/route resolver. You could add a guard/resolver to each route and have it read your data property.

Here is an example resolver:

import { Injectable } from '@angular/core';
import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';

import { Observable } from 'rxjs/Observable';

import { IMovie } from './movie';
import { MovieService } from './movie.service';

@Injectable()
export class MovieResolver implements Resolve<IMovie> {

    constructor(private movieService: MovieService,
                private navigationService: NavigationService) { }

    resolve(route: ActivatedRouteSnapshot,
            state: RouterStateSnapshot): boolean {
        const title = route.data['title'];
        this.navigationService.changeTitle(title);
        return true;
    }
}

Something like the above.




回答2:


There are many ways to handle this. One possible solution is to listen to router events and based on them decide about what content should be displayed.

This approach would reguire importing navigation state first, for example, when route change ended. Like this:

import { Router, NavigationEnd } from '@angular/router';

then you need to subscirbe to that, for example like this.

constructor ( private router:  Router ) {
router.events.subscribe( (event) => ( event instanceof NavigationEnd ) && this.handleRouteChange() )

}

Once you are able to detect change in navigation you can see, what route it is and based on that make further deccisions. For example like this:

  handleRouteChange = () => {
    if (this.router.url.includes('some_key_part_of_url') {
     do what ever you want to do with your content...
    }
  };

You do not necessarily analyse the actual content of the url, you may decide on other router properties. Please, read the docs on router.



来源:https://stackoverflow.com/questions/48446775/angular-how-to-change-navmenu-header-based-on-route

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!