app-route icon indicating copy to clipboard operation
app-route copied to clipboard

Pathname "/" matches "/:pattern"

Open keanulee opened this issue 8 years ago • 6 comments

Description

When using path (i.e. non-hash) routing and at the root domain (e.g. "http://localhost"), <carbon-route pattern="/:pattern"> becomes active and the data object becomes { pattern: '' } (empty string mapped to pattern).

Expected outcome

The <carbon-route> should not match.

Actual outcome

The <carbon-route> matches and data is { pattern: '' }.

Live Demo

(No demo since it's hard to make one with jsbin paths :( )

Steps to reproduce

    <carbon-location route="{{route}}"></carbon-location>
    <carbon-route
        route="{{route}}"
        pattern="/:pattern"
        active="{{isActive}}"
        data="{{data}}"></carbon-route>

Browsers Affected

All browsers

keanulee avatar Apr 27 '16 18:04 keanulee

For me this is intended behavior. If this would not work, the selection of a home-page within an iron-pages would not be possible and significantly degrades the developer experience using this element. Therefore I would vote to keep the current behavior as this is more intuitive.

TimvdLippe avatar Apr 30 '16 13:04 TimvdLippe

You can avoid this match preceding another app-rote to math the "/". Something like:

<app-location route="{{route}}"></app-location>
<app-route
    route="{{route}}"
    pattern="/">
</app-route>
<app-route
    route="{{route}}"
    pattern="/:pattern"
    active="{{isActive}}"
    data="{{data}}">
</app-route>

This only happens with root path. If you are in the next situation this doesn't happen.

<app-route
    route="{{route}}"
    pattern="/:pattern"
    active="{{isActive}}"
    data="{{patterData}}"
    tail="{{patternTail}}">
</app-route>
<app-route
    route="{{patternTail}}"
    pattern="/:pattern2"
    active="{{isActive2}}"
    data="{{data}}">
</app-route>

In this case we have this scenarios:

  • localhost --> isActive === true & isActive2 === false
  • localhost/ --> isActive === true & isActive2 === false
  • localhost/path --> isActive === true & isActive2 === false
  • localhost/path/ --> isActive === false & isActive2 === true
  • localhost/path/path2 --> isActive === false & isActive2 === true

jorgecasar avatar May 03 '16 08:05 jorgecasar

Just bumped into this and the inconsistency is bothering me.

I agree with @TimvdLippe that, on the root that is the intended behaviour you find in all frameworks. I.e.(using the example above by @jorgecasar):

  • http://localhost and http://localhost/: both should match (isActive === true) and patternData should yield {pattern: ''}

But how is this different for nested routes? I would expect:

  • http://localhost/path and http://localhost/path/: both to match (isActive2 === true) and data to yield {pattern2: ''}

But that is not the case. As @jorgecasar mentions, the second matches, the first doesn't. This is because app-location (and window.location.pathname underneath) is setting the route.path to '/', but when using the tail to pass the remaining path to the nested app-route element, it's not doing the same (i.e. patternTail.route is '' instead of '/').

How to achieve composition and isolation? I should be able to move a component into the root or within a nested path without issues.

joaovieira avatar Aug 03 '16 14:08 joaovieira

I'm having this exact same issue and is driving me crazy. I can't be polluting my nested routes like that. I could potentially forget about one . Is it possible to do a regex inside the "pattern"? That way we could always do: /?:pattern

superjose avatar Aug 08 '16 15:08 superjose

This thread is over a year old now. I wanted to post a possible workaround for the missing trailing slash issue, since it doesn't appear that this is of high priority.

<app-location route="{{route}}"></app-location>
<app-route route="{{route}}" pattern="/:page" tail="{{subroute}}"></app-route>
<app-route route="{{subroute}}" pattern="/:id" data="{{subrouteData}}"></app-route>

In your polymer element, setup an observer for subroute.path. If it is an empty string, you can then modify the subrouteData.id property.

observers: [
  '_onSubroute(subroute.path)'
],
_onSubroute: function(subroutePath) {
  if(subroutePath === '') {
    this.set('subrouteData.id', '');
  }
}

cloudily avatar Oct 30 '17 03:10 cloudily

@cloudily Thanks for the workaround, I"ll keep this around ;)

superjose avatar Oct 30 '17 05:10 superjose