2017-01-05 3 views
12

У меня есть приложение с угловым 2 с несколькими видами гнездовых детей. Но он будет отображаться на той же странице, хотя несколько router-outlet.Угловой 2 - Проверить действующий маршрут «имя»

const routes: Routes = [ 
    { 
     path: 'queue/:date/:offset/:type', 
     component: BundleListComponent, 
     resolve: { 
      response: BundleListResolve 
     }, 
     children: [ 
      { 
       path: ':bundleId', component: PointListComponent, 
       resolve: { 
        response: PointListResolve 
       }, 
       children: [ 
        { 
         path: ':pointId', component: TaskListComponent, 
         resolve: { 
          response: TaskListResolve 
         }, 
         children: [ 
          { 
           path: ':taskId', component: TaskDetailComponent, 
           resolve: { 
            response: TaskDetailResolve 
           } 
          }, 
          { path: '', component: EmptyComponent } 
         ] 
        }, 
        { path: '', component: EmptyComponent } 
       ] 
      }, 
      { path: '', component: EmptyComponent } 
     ] 

    }, 
    { 
     path: 'queue', 
     component: QueueRedirectComponent 
    } 
} 

Поэтому в основном я могу путешествовать по списку маршрута

  • /очереди
  • /очереди /:/Дата: офсет/Тип
  • /очередь /:/Дата: офсет /: тип /: BundleID
  • /очередь /: дата /: смещение /: тип /: BundleID /: pointId
  • /очередь /: дата /: смещение /: тип /: BundleID /: pointId /: TaskID

Например

#/queue/2017-01-05/480/20/57f4c26507b36e3684007b52/1/57fb0abb07b36e39d8e88df8/1 

Представьте у вас есть страница с некоторым элементом:

  1. Одна часть UI показал список фильмов
  2. Другая часть показывает детали фильма при нажатии на в списке фильмов, но отображается на одной странице.
  3. Другая часть, чтобы показать деталь персонажа при нажатии на имя символа в деталях фильма, а также показать на той же странице.
  4. и т.д ...

В принципе, я до сих пор можно щелкнуть в списке фильмов в то время как я просмотре подробно характер.

Поиск определения имени для каждого маршрута, но, похоже, весь отчет об ответах эта функция уже удалена с Angular 2 final. В Angular 1 с использованием UI-маршрутизатора я могу определить имя для каждого маршрута и легко получить маршрут с помощью встроенной функции state.is(ROUTE_NAME).

Итак, что я делаю сейчас, это основание на window.location, чтобы получить URL-адрес и разбить эту строку на /, чтобы получить количество параметров. Но это более жестко закодированное.

Есть ли опыт в том, чтобы делать то же самое? Как я могу различить, какой маршрут в данный момент активен?

+0

Возможный дубликат: http://stackoverflow.com/questions/34597835/how-to-get-current -route – hakamairi

+0

Я уже проверял это, прежде чем спрашивать. Потому что мой маршрут содержит только динамический идентификатор. Таким образом, получить URL-адрес от маршрутизатора или из окна будет делать то же самое. Мне нужна возможность отличить маршрут :) – trungk18

+0

Извините, вы правы. Как насчет этого;) http://stackoverflow.com/questions/34323480/in-angular-2-how-do-you-determine-the-active-route – hakamairi

ответ

4

Я считаю, что есть проблема с ответом Скотта, где он использует ActivatedRoute внутри конструктора службы. Этот маршрут не будет обновляться.

Я думал о другом решении, которое может заглянуть в ваш интерес.Он снова идет вниз по использованию data собственности на маршрутах, но теперь с помощью другой службы постановляю:

Вы будете нуждаться в RouterConfig, как это, где для каждого маршрута вы добавить state: StateResolve и объект данных, содержащий имя состояния :

const routes: RouterConfig = [{ 
    path: 'queue/:date/:offset/:type', 
    component: BundleListComponent, 
    resolve: { 
     response: BundleListResolve, 
     state: StateResolve 
    }, 
    data: { 
     state: 'Bundle' 
    }, 
    ... 
] 

не забудьте добавить службу StateResolve в массив поставщиков

Ваш StateResolve сервис будет выглядеть примерно так:

@Injectable() 
export class StateResolve implements Resolve<string> { 

    constructor(private stateService: StateService) {} 

    resolve(route: ActivatedRouteSnapshot): string { 
     let state: string = route.data['state'] 
     this.stateService.setState(state); 
     return state; 
    } 
} 

Очевидно, что вы будете нуждаться в StateService, который имеет метод setState, но я предполагаю, что здесь это довольно понятно.

Возможно, использование защитного устройства resolve немного эксцентрично, но если вы думаете об этом, вы пытаетесь разрешить данные, прежде чем показывать маршрут. В этом случае состояние внутри переменной данных, поэтому имеет смысл использовать Resolve для доступа к свойству data

+0

Спасибо, Пьер, извините за ответ.Наконец, я решил использовать ваш подход, потому что, как вы сказали, я пытаюсь разрешить данные, прежде чем показывать маршрут. – trungk18

+1

@ trungk18 рад, что я мог бы помочь. Я использую эту реализацию и во всех своих приложениях :) К сожалению, щедрость уже отдана, но все дело в помощи, правильно :) – PierreDuc

2
  • Я бы создал простой сервис, который отслеживает активное состояние.
  • Эта услуга может быть введена, если необходимо, получить или установить активное состояние.
  • Вы уже используете Resolvers, так что вы можете установить идентификатор состояния.

Создание службы под названием ActiveState:

import {Injectable} from "@angular/core"; 
import {Observable} from "rxjs"; 

@Injectable() 
export class ActiveState { 

    public current : Observable<string>; 
    private observer : any; 

    constructor() 
    { 
    // Create an observable (it can be subscribed to) 
    this.current = new Observable(observer => { 
     this.observer = observer; 
     observer.next('Unknown'); // The default unknown state 
    }); 
    } 

    setActive(name : string) : void 
    { 
    this.observer.next(name); 
    } 
} 

В ваших резольверами, таких как PointListResolve ... TaskListResolve и т.д.

import {Resolve, ActivatedRouteSnapshot} from "@angular/router"; 
import {Injectable} from "@angular/core"; 
import {Observable} from "rxjs"; 
import {ActiveState} from "services/ActiveState.service"; 

@Injectable() 
export class PointListResolver implements Resolve<any> { 

    // Inject the ActiveState in your constructor 
    constructor(private state : ActiveState) {} 

    resolve(route: ActivatedRouteSnapshot): Observable<any> { 
    // Set the active state name 
    this.state.setActive("Point"); // We are here: /queue/:date/:offset/:type/:bundleId/:pointId 

    // Do your regular resolve functionality (if you don't need to resolve, this blank resolver of an empty object will work) 
    // ... 
    return Observable.of({}); 
    } 
} 

Таким образом, в других преобразователях необходимо обновить значение this.state.setActive("") по мере необходимости.


Затем определить, какие состояния вы находитесь, впрыснуть ActiveState, где вы хотите использовать текущее состояние, например, в @Component, т.е.

import {Component, OnDestroy} from '@angular/core'; 
import {ActiveState} from "services/ActiveState.service"; 

@Component({ 
    selector: 'my-current-state-component', 
    template: `The current state is: {{stateName}}`, 
}) 
export class MyCurrentStateComponent implements OnDestroy { 

    public stateName : string; 
    private sub : Subscription; 

    // Inject in ActiveState 
    constructor(private state : ActiveState) 
    { 
    // Subscribe to the current State 
    this.sub = state.current.subscribe(name => { 
     this.stateName = name; 

     // Other logic to perform when the active route name changes 
     ... 
    }); 
    } 

    ngOnDestroy() 
    { 
    this.sub.unsubscribe(); 
    } 
} 

Примечания:

  • Не забудьте зарегистрировать свой ActiveState в качестве Provider в:

    @NgModule({ 
        ... 
        providers:[ActiveState] 
        ... 
    }) 
    export class AppModule { } 
    
  • Simpler - ненаблюдаемая Version Я использовал Observable<string> поэтому изменения в активном состоянии может быть subscribed, но это может быть упрощена, чтобы быть просто string, если вы не хотите, что функциональность:

    import {Injectable} from "@angular/core"; 
    
    @Injectable() 
    export class ActiveState { 
    
        public current : string; 
    
        setActive(name : string) : void 
        { 
        this.current = name; 
        } 
    
        is(name : string) : boolean 
        { 
        return name == this.current; 
        } 
    } 
    

    Затем, когда вы впрыснуть state : ActiveState вы можете просто проверить значение state.is("Point")

Я надеюсь, это полезно.

9

Создать службу под названием ActiveState который будет subscribe к изменениям в маршрутизатор, используя router.events.subscribe:

import {Injectable} from "@angular/core"; 
import {Router, ActivatedRoute, NavigationEnd} from "@angular/router"; 

@Injectable() 
export class ActiveState { 

    public name : string; 

    constructor(router : Router, route : ActivatedRoute) 
    { 
    router.events.subscribe(event => { 
     if(event instanceof NavigationEnd){ 

     // Traverse the active route tree 
     var snapshot = route.snapshot; 
     var activated = route.firstChild; 
     if(activated != null) { 
      while (activated != null) { 
      snapshot = activated.snapshot; 
      activated = activated.firstChild; 
      } 
     } 

     // Try finding the 'stateName' from the data 
     this.name = snapshot.data['stateName'] || "unnamed"; 
     } 
    }); 
    } 

    is(name : string) : boolean 
    { 
    return this.name === name; 
    } 
} 

Затем на маршруте мы добавим простое значение по data парам маршрута называется stateName для каждого государства мы хочу назвать:

const routes: Routes = [ 
{ 
    path: 'queue/:date/:offset/:type', 
    component: BundleListComponent, 
    resolve: { response: BundleListResolve } 
    data: { stateName: 'Bundle' }, 
    children: [ 
     { 
      path: ':bundleId', component: PointListComponent, 
      resolve: { response: PointListResolve }, 
      data: { stateName: 'Point'} 
     } 
    ... 

Тогда, когда вы впрыснуть state : ActiveState вы можете просто проверить значение state.is("Point")

+0

Спасибо Скотту за отличный ответ. – trungk18

+0

@ trungk18 Добро пожаловать. Надеюсь, это полезно. :) Я бы хотел, чтобы государства могли быть названы тоже. – Scott

+0

Да, я думаю, что название штата очень полезно. – trungk18

2

name был удален некоторое время назад из маршрутов, а маршруты позволяют добавлять произвольные данные

const routes: RouterConfig = [ 
    { 
     path: '', 
     redirectTo: '/login', 
     pathMatch: 'full', 
    }, 
    { 
     path: 'login', 
     component: LoginComponent, 
     data: {title: 'Login'} 
    }, 
    { 
     path: 'home', 
     component: HomeComponent, 
     data: {title: 'Home'} 
    }, 
    { 
     path: 'wepays', 
     component: WePaysComponent, 
     data: {title: 'WePays'} 
    } 
]; 

Этот код создает заголовок из имен всех сегментов маршрута. Возможно, это будет упрощено для вашего случая использования.

export class AppComponent { 
    constructor(titleService:Title, router:Router, activatedRoute:ActivatedRoute) { 
    router.events.subscribe(event => { 
     if(event instanceof NavigationEnd) { 
     var title = this.getTitle(router.routerState, router.routerState.root).join('-'); 
     console.log('title', title); 
     titleService.setTitle(title); 
     } 
    }); 
    } 

    // collect that title data properties from all child routes 
    // there might be a better way but this worked for me 
    getTitle(state, parent) { 
    var data = []; 
    if(parent && parent.snapshot.data && parent.snapshot.data.title) { 
     data.push(parent.snapshot.data.title); 
    } 

    if(state && parent) { 
     data.push(... this.getTitle(state, state.firstChild(parent))); 
    } 
    return data; 
    } 
} 

Смотрите также Changing the page title using the Angular 2 new router

+0

Спасибо, человек! Как всегда, все ваши ответы просто великолепны и полезны. – neoswf

Смежные вопросы