Skip to content

Commit

Permalink
feat(router): add ability to unregister a route (#60)
Browse files Browse the repository at this point in the history
Closes #49
  • Loading branch information
meeroslav committed Nov 20, 2020
1 parent 1b868fd commit e8cff9b
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 4 deletions.
58 changes: 57 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ yarn add angular-routing

## Installation with ng add

You can use ng add to install the package by using below command.
You can use ng add to install the package by using the command below.

```sh
ng add angular-routing
Expand Down Expand Up @@ -85,6 +85,62 @@ After your components are registered, use the `Router` and `Route` components to
</router>
```

## Route sorting

Angular routing is sorting the routes upon registration, based on priority. The order in which the routes are defined in your template is therefore not important.

The following two examples will give the same results

```html
<router>
<route path="/blog" [exact]="false">
<app-blog *routeComponent></app-blog>
</route>
<route path="/" redirectTo="/blog"></route>
<route path="/" [exact]="false">
<app-page-not-found *routeComponent></app-page-not-found>
</route>
</router>
```

and

```html
<router>
<route path="/" [exact]="false">
<app-page-not-found *routeComponent></app-page-not-found>
</route>
<route path="/" redirectTo="/blog"></route>
<route path="/blog" [exact]="false">
<app-blog *routeComponent></app-blog>
</route>
</router>
```

The sorting algorithm has only a few rules (ordered by importance):

- Named routes (e.g. `/blog`) have priority over root route (`/`)
- Static routes (e.g. `/blog/view`) have priority over parametrized (e.g. `/blog/:id`)
- Exact route (with `exact` set to `true` or omitted) has priority over non-exact (with `exact` set to `false`)
- Longer paths have priority over shorter

## Route restrictions

Implementing the route restriction is as simple as adding a structural directive on a `route` component

```html
<router>
<route path="/admin" *ngIf="user.isAuthenticated$ | async">
<app-admin *routeComponent></app-admin>
</route>
<route path="/admin" *ngIf="!(user.isAuthenticated$ | async)">
<app-login *routeComponent></app-login>
</route>
</router>
```

The restriction doesn't stop the navigation. It simply removes the route from the configuration so the next eligible route will pick it up.

## Navigating with Links

Use the `linkTo` directive with a _full path_ to register links handled by the router.
Expand Down
1 change: 1 addition & 0 deletions libs/angular-routing/src/lib/route.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ export class RouteComponent implements OnInit, OnDestroy {
}

ngOnDestroy() {
this.routerComponent.unregisterRoute(this.route);
this.destroy$.next();
}

Expand Down
21 changes: 18 additions & 3 deletions libs/angular-routing/src/lib/router.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ interface State {
routes: Route[];
}

type UnregisterableRoute = Route & { unregister?: boolean };

@Component({
// tslint:disable-next-line:component-selector
selector: 'router',
Expand Down Expand Up @@ -115,9 +117,7 @@ export class RouterComponent implements OnInit, OnDestroy {
});

route.matcher = route.matcher || routeRegex;

const routes = this.state$.value.routes;
this.updateState({ routes: routes.concat(route).sort(compareRoutes) });
this.updateRoutes(route);

return route;
}
Expand All @@ -126,6 +126,10 @@ export class RouterComponent implements OnInit, OnDestroy {
this.updateState({ activeRoute });
}

unregisterRoute(route: Route) {
this.updateRoutes({ ...route, unregister: true });
}

normalizePath(path: string) {
return this.router.normalizePath(path);
}
Expand Down Expand Up @@ -155,4 +159,15 @@ export class RouterComponent implements OnInit, OnDestroy {
private updateState(newState: Partial<State>) {
this.state$.next({ ...this.state$.value, ...newState });
}

private updateRoutes(route: UnregisterableRoute) {
const routes = this.state$.value.routes;
if (route.unregister) {
this.updateState({
routes: routes.filter((r) => r.matcher !== route.matcher),
});
} else {
this.updateState({ routes: routes.concat(route).sort(compareRoutes) });
}
}
}

0 comments on commit e8cff9b

Please sign in to comment.