Jonas Arcangel
Jonas Arcangel

Reputation: 1925

Forward Slash in Angular Route Parameters

How do I set up my routes so that my parameter can take forward slashes?

For example: myapp.com/file/rootfolder/subfolder/myfile

This doesn't work:

const SECTION_ROUTES: Routes = [
    { path: 'file/:path', component: FileStoreComponent }
];

Is having / in routing parameter values possible?

I've read about URL approaches that use URL encoding. However, I'd like my user to be able to type the URL.

Upvotes: 9

Views: 12675

Answers (5)

Mark Lagendijk
Mark Lagendijk

Reputation: 6893

This can be achieved by using a UrlMatcher.

To keep the matcher as simple as possible, we can use a parent route for the file segment of the route, and then use a childRoute that handles the remaining path.

const SECTION_ROUTES: Routes = [
  {
    path: "file",
    children: [{
      matcher: (segments: UrlSegment[]) => ({
        consumed: segments,
        posParams: {
          path: new UrlSegment(segments
              .map((segment) => decodeURIComponent(segment.path))
              .join("/"), 
              {}
          ),
        },
      }),
      component: FileStoreComponent 
    }],
  },
];

Upvotes: 0

Marek Rr
Marek Rr

Reputation: 1

Adding <base href="/"> to index.html helped me.

Upvotes: -2

Matt
Matt

Reputation: 2290

try this for matching on path :path

const SECTION_ROUTES: Routes = [
    { 
        matcher: t => t.length ? { consumed: t, posParams: { path: new UrlSegment(t.join('/'), {}) } } : null, 
        component: FileStoreComponent 
    }
];

Upvotes: 0

Thibaut A.
Thibaut A.

Reputation: 171

To achieve this with a recent version of Angular (9.X for me), you can use the Route.matcher parameter. Here is an example:

function filepathMatcher(segments: UrlSegment[], 
                         group: UrlSegmentGroup, 
                         route: Route) : UrlMatchResult {
  // match urls like "/files/:filepath" where filepath can contain '/'
  if (segments.length > 0) {
    // if first segment is 'files', then concat all the next segments into a single one
    // and return it as a parameter named 'filepath'
    if (segments[0].path == "files") {
      return {
        consumed: segments,
        posParams: {
          filepath: new UrlSegment(segments.slice(1).join("/"), {})
        }
      };
    }
  }
  return null;
}

const routes: Routes = [
  { path: 'login', component: LoginComponent },
  { matcher: filepathMatcher, component: FilesComponent },
  // ...
];

@NgModule({
  imports: [RouterModule.forRoot(routes, { useHash: true })],
  exports: [RouterModule]
})
export class AppRoutingModule { }

You will be able to access the parameter in your Component through the ActivatedRoute.paramMap

Note the query parameters are also working and preserved.

However, you will still have issues if the URL contains parenthesis, for example /files/hello(world:12)/test because they are interpreted by angular as auxiliary routes

In this case, you can add a custom UrlSerializer to encode parenthesis and you'll have to decode them in your Component.

Upvotes: 7

StephenRios
StephenRios

Reputation: 2232

It looks like you have to escape each forward slash with a wildcard like so:

/*page

This question covers it: Angular2 RouterLink breaks routes by replacing slash with %2F

That question links to the following GitHub issue ticket that goes more in-depth: https://github.com/angular/angular/issues/8049

Upvotes: 1

Related Questions