Pat M
Pat M

Reputation: 6036

Angular2 - How to use router with dynamic urls

Suppose I have this nested itemListComponent, which is a child of a rootComponent, using the following template:

<span *ngFor="#item of list">
    <a [routerLink]="[item.url]">{{item.title}}</a> |
</span>

The path item.url, which is provided from a Json service, could have one of the following path structure:

Examples:

category2/987654/hello-world
category2/123456/hi-teacher
category3/554433/yo-brother

How could @RouteConfig be implemented so that these links use a itemDetail component?

Sorry if this does not look very detailed. I did not find a clear how-to-guide for routing urls that are provided by a service with full paths (not assembled paths)

Upvotes: 11

Views: 23409

Answers (3)

Ivan Pianetti
Ivan Pianetti

Reputation: 749

Try this:

<span *ngFor="#item of list">
   <a [routerLink]="['/category', item.url]">
        {{item.title}}
   </a>
</span>

routes.ts:

{path: "category/:id", component: CategoryComponent}

Upvotes: 30

Pat M
Pat M

Reputation: 6036

Although Eric's solution using regexes works fine using HashLocationStrategy, the solution I used is based on this article and Plunk by Yavo Fain.

I then converted to a PathLocationStrategy (using APP_BASE_HREF. See official doc)

To make the PathLocationStrategy work we need to make the index.html as the default fallback page on the server side. Here is an example using gulp-webserver:

gulp.task('webserver', function() { 
    gulp.src('app') .pipe(webserver({ 
        fallback: 'index.html' 
    })); 
});

We need to use routerLink with a PathLocationStrategy. Otherwise the browser will refresh the page when routing to urls and it won't completely behave like a one-page app.

I could then use *ngFor loop to render different items with different paths and ids.

<div *ngFor="#item of list">
    <a [routerLink]="['ContentId', {id:item.url}]">{{item.title}}</a>
</div>

Upvotes: 0

Eric Martinez
Eric Martinez

Reputation: 31787

That's what regex matches are for. But if you have pre-assembled URLs you may not want to use routerLink with them. RouterLink expects an array, you will have to use simple URLs.

Consider your original snippet

<span *ngFor="#item of list">
    <a [href]="item.url">{{item.title}}</a> |
</span>

Assuming you're using HashLocationStrategy your URL should contain the hash

<span *ngFor="#item of list">
    <a [href]="'#/' + item.url">{{item.title}}</a> |
</span>

That should result in an URL like this

#/category2/987654/hello-world

Now that we have the URLs correctly formed, we can use the regex matchers we mentioned earlier

@RouteConfig([
  {
    name : 'ItemDetail',

    // regex that will match the URL in the href or the URL typed directly by the user
    regex : '^([a-z0-9]+)/([0-9]+)/([a-z\\-]+)$',

    // serializer is mandatory, but it is used when you have a routerLink with params
    serializer : (params) => {
      return new GeneratedUrl(`${params.a}/${params.b}/${params.c}`)
    },
    component : ItemDetail
  }
])

This is the easiest if you have pre-assembled URLs.

See this plnkr with an example working.

Note that regex matchers were introduced in beta.9 and they contain a few issues, see

You may found other ones.

I really apologize for my bad regex skills, probably you can bypass it, but hopefully you'll get the idea.

Upvotes: 3

Related Questions