2016-12-23 3 views
1

Мне не нравится использовать router.navigate, потому что для этого требуется использовать магическую строку по всему приложению. КакСильно типизированная обертка вокруг router.navigate

this.router.navigate(['/user', user.id]); 

Так что я хотел бы создать строго типизированный обертку вокруг него:

export class NavigatorService { 

    constructor(private router: Router) {} 

    public user(userId: number): Promise<boolean> { 
    return this.router.navigate(['/user', user.id]); 
    } 
} 

Конечно, это должно быть синхронизированы с конфигурацией маршрутизации.

Что беспокоит меня является использование в шаблонах:

<a [routerLink]="['/user', user.id]"> 
</a> 

Должен ли я добавить дополнительный метод, который возвращает массив?

export class NavigatorService { 

    ... 

    public userArr(userId: number): Array<any> { 
    return ['/user', user.id]; 
    } 
} 

<a [routerLink]="navigator.userArr(user.id)"> 
</a> 

Любые идеи? Может быть, кто-то уже пошел по этой дороге?

ответ

0

После некоторого мышления я решил, что для простого маршрут я хочу следующую подпись службы:

class NavigatorService { 
    user(id: number, matrix: MatrixParams = {}): Navigation { ... } 
} 

где MatrixParams является простым объектом

interface MatrixParams { 
    [index: string]: any 
} 

и Navigation является расширенным массивом:

interface Navigation extends Array<any> { 
    go(extras?: NavigationExtras): Promise<boolean>; 
} 

Navigation может быть использован как в коде и в routerLink директивы:

this.navigator.user(1).go(); 
<a [routerLink]="navigator.user(1)">...</a> 

Для создания такого объекта я использовал подклассы массивов, как описано here:

function navigation(router: Router, ...items: any[]): Navigation { 
    let arr: Navigation = <Navigation>[...items]; 

    arr.go = (extras?: NavigationExtras): Promise<boolean> => { 
     return router.navigate(arr, extras); 
    }; 

    return arr; 
} 

Так реализация сервиса будет:

class NavigatorService { 
    constructor(private router: Router) { } 

    user(id: number, matrix: MatrixParams = {}): Navigation { 
     return navigation(this.router, '/user', id, matrix); 
    } 
} 

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

class NavigatorService { 
    ... 

    order(id: number, matrix: MatrixParams = {}): OrderNavigation { 
     return orderNavigation(this.router, '/order', id, matrix); 
    } 
} 

interface OrderNavigation extends Navigation { 
    items(matrix?: MatrixParams): Navigation; 
} 

function orderNavigation(router: Router, ...items: any[]): OrderNavigation { 
    let arr: OrderNavigation = <OrderNavigation>navigation(router, ...items); 

    arr.items = (matrix: MatrixParams = {}): Navigation => { 
     return navigation(router, ...arr, 'items', matrix); 
    }; 

    return arr; 
} 
0

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

[myRouterLink]="32" 

https://github.com/angular/angular/blob/a006c1418a9f4d44f4046976c0ee2824416aa096/modules/%40angular/router/src/directives/router_link.ts#L82-L128

+0

Вы имеете в виду создание пользовательской директивы для каждого маршрута? –

+0

Нет, вы только создаете директиву один раз и помещаете его в модуль, например 'MyRouterModule', на' declarations: [MyRouterLinkDirective] 'и экспортируете: [MyRouterLinkDirective]', а затем везде, где вы используете директиву, добавьте модуль в 'import: [ MyRouterModule] 'и' [myRouterLink] = "32" 'станет экземпляром' MyRouterLinkDirective' везде. –

+0

Я имел в виду немного другую вещь. Что [[myRouterLink] = "32" 'равно?Если он равен '[routerLink] =" ['/ user', 32] ", тогда мне нужно создать другую директиву для разных маршрутов ('/ user', '/ client', '/ order' и т. Д.) –

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