GithubHelp home page GithubHelp logo

angular-component / router Goto Github PK

View Code? Open in Web Editor NEW
256.0 256.0 16.0 1.04 MB

Angular Component Router - A declarative router for Angular applications

License: MIT License

TypeScript 93.81% JavaScript 2.42% CSS 1.09% HTML 2.68%
angular component declarative router

router's People

Contributors

allcontributors[bot] avatar brandonroberts avatar kylecannon avatar meeroslav avatar santoshyadavdev avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

router's Issues

[Feat] Investigate changing route component to a structural directive

Currently we use a route component to define a route.

<route path="/">
  <my-component *routeComponent></my-component>
</route>
  • This has an easy mental model for registering a route
  • Provides an easy way to pass route params as inputs.
  • Provides a placeholder for rendering lazy loaded components
<route path="/" #myComponenRoute>
  <my-component *routeComponent [params>="myComponentRoute.routeParams$ | async"></my-component>
</route>
  • Extra DOM elements that have to rendered
  • It wraps the actual component, which might make it more difficult to style
  • Can't use display: none on the route element

This effort would look at potential options to use a structural directive to register the route, and have the route component rendered in its place with no wrapper.

Thoughts

  <my-component *route path="/home"></my-component>
  <ng-template *route path="/lazy" [load]="components.lazy"></ng-template>

Reference: https://twitter.com/LayZeeDK/status/1285969664917614592?s=20

feat: Support default exports

When lazy loading NgModules and Components, support loading them without the .then and allow them to be exported as default.

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

@Component({
  template: `
    <router>
      <route path="/lazy" [load]="components.lazy"> </route>
    </router>
  `,
})
export class MyComponent {
  components = {
    lazy: () => import('./lazy/lazy.component')
  };
}

[Bug] Nested routes do not abide 404

With parent router set as

 <router>
    <route path="/home">
      <app-home *routeComponent></app-home>
    </route>
    <route path="/user/**">
      <app-user *routeComponent></app-user>
    </route>
    <route path="/" redirectTo="/home"></route>
    <route path="**">
      <app-not-found *routeComponent></app-not-found>
    </route>
  </router>

And user router set as:

<router>
    <route path="/:id">
      <app-user-profile *routeComponent></app-user-profile>
    </route>
    <route path="/">
      <app-user-list *routeComponent></app-user-list>
    </route>
  </router>

Actual:
The following route is handled as correct: '/user/first/second/third' and the UserProfile component would extract id param as third.

Expected:
The router responds with 404 and renders the NotFound component.

Dynamic Urls

Hi Brandon,
Thank you for this initiative !
Regarding to my experience working with Angular, the router and Drupal, I would like to give you some points to get in mind regarding routing.
In real web projects, I think we can't rely on static urls to route components. Using Drupal as backend, for example, the url are managed by the contributors, and Angular can't know all of them.

For SEO or readability reason, a news can have a url like that :
in english :
https://www.mydomain.com/en/07/14/2020/my-great-news
in french :
https://www.mydomain.com/fr/14/07/2020/ma-super-news

I think we shouldn't trust the url only to take the routing decision and, in fine, the application structure. To my point of view, the Angular defined urls should be only technical/internal and not necessarily displayed.

In the projets I'm working on, I create some routes "templates" by contentTypes (empty paths, component, data etc.). When I get the url, if I don't know what is this url, I ask Drupal for it (on direct access only / app boot), regarding to the content type, I check my route templates to find the right route. Once I found it, I update its path (with the Drupal one, to get also a nice url), if the route is not in the Router configs, then I add it, then I navigateToUrl.
Thanks to this approach I can also mix static routes.

I just wanted to give you another point of view ;-)

Good luck !

[Feat] Sort routes by `path` and `exact` on registering

This is precondition to guards on RouteComponent using structural directive.

At the moment, each route with structural directive will be registered asynchronously, landing in the routes array most likely after wildcard/catch-all route. Additionally, this allows user to define routes without worrying about the correct order.

Rough logic:

this.routes$ = this._routes$.pipe(scan((routes, route) => {
  routes = routes.concat(route).sort((a, b) => {
    if (b.path < a.path) { return -1; }
    if (a.path < b.path) { return 1; }
    if (a.options.exact < b.options.exact) { return -1; } // additional checks for missing `exact` param needed
    if (a.options.exact > b.options.exact) { return 1; }
    return 0;
  });
  return routes;
}));

[Feat] Provide access to all route params via router service

Components can access their dedicated URL param via RouteParams provider.
Sometimes, components need to be aware of all the params in the URL. This should ideally be provided via router service.
Router survive provides access to url$, queryParams$, and hash$ stream, but not path params.

[Feat] Enable route guards

Route unregister should be called upon route destroy. Unregistering route will remove it from the routes$ and trigger navigation. This is precondition to having route guards using structural directives.

The intended behaviour is different to @angular/router canActivate:

Guard true false
@angular/router navigate to route stop navigation
angular-routing navigate to route navigate to fallback route

Consider new name

The current name angular-routing is too similar to @angular/router. This would lead to confusion. Additionally, the name is too generic leading to difficulty when using search engines (searching for angular routing would most likely point to numerous articles and docs on @angular/router).

Let's try to brainstorm here possible names in the following format.

Suggested name: FooBar
Explanation(if needed): Foo is to angular was Bar is to routing

[Question] RouteComponentDirective seems obsolete

Based on the code, the sole purpose of RouteComponentTemplate is to provide TemplateRef for RouteComponent to use as the container outlet. These are equivalent:

  • Current custom directive
<route path="/blah">
  <app-something *routeComponent></app-something>
</route>
  • Any structural directive
<route path="/blah">
  <app-something *ngIf></app-something>
</route>
  • No directive, just template
<route path="/blah">
  <ng-template>
    <app-something></app-something>
  </ng-template>
</route>

Seems unnecessary to define custom directive when ng-template within RouteComponent could solve this.

What was the reasoning behind it? Is RouteComponentTemplate planned to have some logic in the future?

Consider replacing `pathToRegexp` with built-in function

pathToRegexp provides nice functionality for parsing routes, but also includes a lot of functionality we do not use or need.

Simple built-in function could reduce footprint further. Take a look at following:

const wrap = (regexBody: string): string => {
  return `/^${regexBody}/i`
}

const div = '\/';
const end = '$';
const nEnd = '[]|$'; // null or end
const pathEnd = `[\/#\?]`;
const param = `([^\/#\?]+?)`;

const books = wrap(`${div}books(?:${pathEnd}(?=${nEnd}))?(?=${pathEnd}|${nEnd})`); // '/books' + exact false
const login = wrap(`${div}login${pathEnd}?${end}`); // '/login'
const id = wrap(`(?:${div}${param})${pathEnd}?${end}`); // '/:id'
const home = wrap(`${pathEnd}?${end}`); // '/'
const wildcard = wrap(`(?:${pathEnd}(?=${nEnd}))?`); // '/' + exact false

const booksFind = wrap(`${div}books${div}find${pathEnd}?${end}`); // '/books/find'
const booksId = wrap(`${div}books(?:${div}${param})${pathEnd}?${end}`); // '/books/:id'
const booksRoot = wrap(`${div}books${pathEnd}?${end}`); // '/books'
const booksWildcard = wrap(`${div}books(?:${pathEnd}(?=${nEnd}))?(?=${pathEnd}|${nEnd})`); // '/books' + exact false

With these few common patterns we can describe every route matcher Regexp

usage in effects / ofRoute operator

Would something like this be a bad idea? And is there some built-in function that would be able to check if route matches pattern (I imagine link active has to be doing something like that).

private action$ = createEffect(() => this._router.url$.pipe(
  // url is /products/detail/123
  filter((url) => ofRoute('/products/detail/:id', url)),
  tap(console.log)
);

Angular 17: Standalone components support

The ComponentRouterModule.forRoot() is not supported in standalone components' imports.

Error: Component imports must be standalone components, directives, pipes, or must be NgModules.

feat: Support loader function as input for route component

Loaders can be used to fetch data for the component, run checks such as auth, redirect, and more.

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

@Component({
  template: `
    <router>
      <route path="/lazy"
        [load]="components.lazy"
        [loader]="() => Promise<Response> | Observable<Response>">
      </route>
    </router>
  `,
})
export class MyComponent {
  data$: Observable<Data> = getLoaderData();

  constructor(private loaderData$: LoaderData) {}

  components = {
    lazy: () => import('./lazy/lazy.component')
  };
}

[Fix] Nested routes only work for root component

With given main router

<router>
  ...
  <route path="/user">
    <app-user *routeComponent></app-user>
  </route>
  ...
</router>

And nested router in UserComponent:

<router>
  <!-- this works -->
  <route path="/">
    <app-user-list *routeComponent></app-user-list>
  </route>
  <!-- this also works -->
  <route path="">
    <app-user-list *routeComponent></app-user-list>
  </route>
  <!-- this does not work -->
  <route path="/profile">
    <app-user-profile *routeComponent></app-user-profile>
  </route>
    <!-- this also does not work -->
  <route path="profile">
    <app-user-profile *routeComponent></app-user-profile>
  </route>
</router>

Calling "/user" works but calling "/user/profile" ends up in not found state.

feat: Rename Router Component

Currrently you define routes by using

  <router>
    <route></route>
  </router>

This proposal changes the component to routes

  <routes>
    <route></route>
  </routes>

This aligns with react-router v6+ syntax for declaring groups of routes

[Brand] Logo

Since we have a name, now we need a logo. Ideally, there would be a logo for the whole org angular-component and a visually compatible logo for the router.

What we are looking for:

  • Simplicity (should look nice in color, but also in monochrome)
  • Scalability (should be clear also when scaled down to icon size)
  • Recognizable (using the angular shield is ok, but should differentiate it from the other libs out there)

Proposals can be done in vector (SVG), raster (JPG, PNG), or hand-drawn sketch (in which case we will convert it to vector eventually).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.