Nondigestible Purple Mayonnaise

    @this-dot/route-config
    TypeScript icon, indicating that this package has built-in type declarations

    1.2.3 • Public • Published

    Route Config ⚙️

    Route Config is an Angular library that provides tools to easily set and access the properties defined in RouterModule configuration. It offers some built in tools that work out of the box but also is easily extensible via data property of Angular's Route configuration object.

    It supports:

     Displaying parts of component's template based on the tags defined in the Router config
     Retrieving custom properties defined in currently rendered route
     Type safety for custom properties



    Usage

    Installation

    Install the package:
    npm install @this-dot/route-config
    or
    yarn add @this-dot/route-config

    Using in your Angular app

    It is very simple to add route-config to your Angular app:

    Just import the RouteConfigModule module

    import { RouteConfigModule } from '@this-dot/route-config';

    and add it to the imports array in the Angular module

    @NgModule({
      /* other module props  */
      imports: [RouteConfigModule.forRoot() /* other modules */],
    })
    export class AppModule {}

    The library's elements use Angular's router data object to configure the behavior. See the below examples on how to use it in your application.

    To use library's provided directives and/or pipes just add RouteConfigModule in your submodule that uses them. E.g.

    @NgModule({
      /* other module props  */
      imports: [RouteConfigModule /* other modules */],
    })
    export class YourSubModule {}

    Examples


    RouteTagDirective (*tdRouteTag)

    To configure this directive lets create the following sample router configuration:

    @NgModule({
      declarations: [FirstRouteComponent, SecondRouteComponent],
      imports: [
        RouterModule.forRoot([
          {
            path: 'first',
            component: FirstRouteComponent,
            data: {
              routeTags: ['show'],
            },
          },
          {
            path: 'second',
            component: SecondRouteComponent,
          },
        ]),
      ],
      exports: [RouterModule],
    })
    export class AppModule {}

    Now we can use it in the component's template

    <p *tdRouteTag="'show'">
      This text is only visible, if there is a 'show' tag in the route data's `routeTags` Array
    </p>
    

    *tdRouteTag provides a way do display a fallback template if a given tag is not present

    <p *tdRouteTag="'show'; else noShowTag">
      This text is only visible, if there is a 'show' tag in the route data's `routeTags` Array
    </p>
    <ng-template #noShowTag>
      <p>There is no 'show' tag in this route's config</p>
    </ng-template>
    

    RouteDataHasDirective (*tdRouteDataHas)

    If you need to use a different route data property to store the tags, you can use the *tdRouteDataHas directive. It works very similar to *tdRouteTag directive but provides a way to use different properties as a source of data. Let's take a look at the following router configuration:

    @NgModule({
      declarations: [FirstRouteComponent, SecondRouteComponent],
      imports: [
        RouterModule.forRoot([
          {
            path: 'first',
            component: FirstRouteComponent,
            data: {
              customDataProperty: ['customShow'],
            },
          },
          {
            path: 'second',
            component: SecondRouteComponent,
          },
        ]),
      ],
      exports: [RouterModule],
    })
    export class AppModule {}

    Now to configure the directive to use the customDataProperty property we can use tdRouteDataHasPropName input to set the desired property name:

    <p *tdRouteDataHas="'customShow'; propName: 'customDataProperty'">
      This text is only visible, if there is a 'show' tag in the route data's `customDataProperty` Array
    </p>
    

    *tdRouteDataHas also provides a way do display a fallback template if a given tag is not present

    <p *tdRouteDataHas="'customShow'; propName: 'customDataProperty'; else noShowTag">
      This text is only visible, if there is a 'customShow' tag in the route data's `customDataProperty` Array
    </p>
    <ng-template #noShowTag>
      <p>There is no 'customShow' tag in this route's config</p>
    </ng-template>
    

    RouteDataDirective (*tdRouteData)

    This directive allows for access to the whole data property defined in the current Route from a Component's template.

    We can use it as following:

    <h1 *tdRouteData="let data">
      Current title is: {{ data.title }}
    </h1>
    

    It is also possible to pass a default value so that if a property is not defined in the Route we will still receive some value:

    <h1 *tdRouteData="let data; defaultValue: { title: 'DefaultTitle', routeTags: ['defaultTag'] }">
      Current title is: {{ data.title }}
    </h1>
    

    If you want to access multiple properties in one component's template it is recommended to wrap the whole template with only one *tdRouteData directive. This approach follows DRY principle and is efficient as it only creates one subscription per template.

    <ng-container *tdRouteData="let data; defaultValue: { title: 'DefaultTitle', routeTags: ['defaultTag'] }">
      <h1>
        Current title is: {{ data.title }}
      </h1>
      <p>
        Current route contains the following tags: {{ data.routeTags | json }}
      </p>
    </ng-container>
    

    RouteConfigService

    In every component you can inject RouteConfigService to get the current route configuration properties.

    export class AppComponent {
      constructor(private routeConfigService: RouteConfigService) {}
    }

    You can use getLeafConfig method to get the Observable with current route's property value

    export class AppComponent {
      tags$ = this.routeConfigService.getLeafConfig('routeTags', ['no tags']);
    }

    Now you can treat it as any other Observable and use e.g. async pipe to display the current value

    <h1>{{ tags$ | async }}</h1>
    

    It is also possible to retrieve the whole data object by using getActivatedRouteConfig:

    export class AppComponent {
      data$ = this.routeConfigService.getActivatedRouteConfig();
      dataWithDefaultValue$ = this.routeConfigService.getActivatedRouteConfig({
        routeTags: ['defaultTag'],
        title: 'Default Title',
      });
    }

    And if you want to use your custom data properties you can create your custom types:

    export type AppRouteConfigParams = 'title';
    
    export type AppRouteTag = keyof typeof AppRouteTags;
    
    export enum AppRouteTags {
      show = 'show',
    }

    and provide them when injecting RouteConfigService

    export class AppComponent {
      title$ = this.routeConfigService.getLeafConfig('title', 'Default Title');
    
      constructor(private routeConfigService: RouteConfigService<AppRouteTag, AppRouteConfigParams>) {}
    }

    In this case your example router config can look like this:

    @NgModule({
      declarations: [FirstRouteComponent, SecondRouteComponent],
      imports: [
        RouterModule.forRoot([
          {
            path: 'first',
            component: FirstRouteComponent,
            data: {
              routeTags: [AppRouteTags.show], // use enum to get more type safety
            },
          },
          {
            path: 'second',
            component: SecondRouteComponent,
            data: {
              title: 'Second Route Title',
            },
          },
        ]),
      ],
      exports: [RouterModule],
    })
    export class AppModule {}

    Providing default value globally

    Both *tdRouteData and RouteConfigService allow for providing a default value in case route data doesn't provide a certain property. It is also possible to provide a default value globally by providing ROUTE_DATA_DEFAULT_VALUE injection token when configuring the root module:

    @NgModule({
      /* other module props  */
      imports: [RouteConfigModule.forRoot() /* other modules */],
      provide: [
        {
          provide: ROUTE_DATA_DEFAULT_VALUE,
          useValue: {
            title: 'Injected Default Title',
            someDefaultParam: 'Some other default param',
          },
        },
      ],
    })
    export class AppModule {}

    This way we don't need to provide default value each time we use *tdRouteData or RouteConfigService. However, if a different default value is necessary it still can be provided - and it will overwrite the value injected with a token.

    The injection token can also be provided / overridden in a component's declaration:

    @Component({
       // ...
       providers: [ /* the value provided here will be the default down in the DOM tree */]
    })

    Install

    npm i @this-dot/route-config

    DownloadsWeekly Downloads

    39

    Version

    1.2.3

    License

    MIT

    Unpacked Size

    132 kB

    Total Files

    30

    Last publish

    Collaborators

    • danetdl
    • jtomchak
    • thisdot-devops
    • dustinsgoodman
    • btapai
    • ktrz__