npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@this-dot/route-config

v1.2.6

Published

A library containing directives and services for configuring components via Route's routeData property

Downloads

32

Readme

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 */]
})

inRouteTags$ pipe

The inRouteTags$ pipe takes an array of route tags and returns an Observable. This observable emits a true value if any of the values in the provided array is in the configured route tags of the activated route.

import { Component } from '@angular/core';

@Component({
  selector: 'custom-component',
  templateUrl: './custom-component.html',
})
export class CustomComponent {
  displayRouteTags = ['custom-component', 'another-tag', 'third-tag'];
}
<!-- custom-component.html -->
<ng-container *ngIf="displayRouteTags | inRouteTags$ | async">
  The contents of this ng-container are only displayed when the activated route's route config has
  the above declared route tags.
</ng-container>