Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions docs/api/route-redirect.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ The route redirect has two configurable properties:
- `from`
- `to`

It redirects "from" a URL "to" another URL. When the defined `ion-route-redirect` rule matches, the router will redirect from the path specified in the `from` property to the path in the `to` property. In order for a redirect to occur the `from` path needs to be an exact match to the navigated URL.
It redirects "from" a URL "to" another URL. When the defined `ion-route-redirect` rule matches, the router will redirect from the path specified in the `from` property to the path in the `to` property. In order for a redirect to occur the `from` path needs to be an exact match to the navigated URL, unless `from` ends in `*`. A `from` that ends in `*` matches any path below it, but not the path itself, so `/admin/*` matches `/admin/posts` but not `/admin`.

To render a "not found" page for unknown paths instead of redirecting, use a [catch-all route](route.mdx#catch-all-routes).

## Multiple Route Redirects {/* #multiple-route-redirects */}

Expand All @@ -58,7 +60,7 @@ If the user navigates to `/admin` the router will redirect to `/login` and stop
will NOT redirect if the user navigates to `/admin/posts` -->
<ion-route-redirect from="/admin" to="/login"></ion-route-redirect>

<!-- By adding the wilcard character (*), the redirect will match
<!-- By adding the wildcard character (*), the redirect will match
any subpath of admin -->
<ion-route-redirect from="/admin/*" to="/login"></ion-route-redirect>
```
Expand Down
103 changes: 103 additions & 0 deletions docs/api/route.mdx

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't need to be done now but we should consider adding a Navigation/Routing guide under JavaScript like the other frameworks have:

I think that would be a better place for this kind of information.

Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,109 @@ Note: this component should only be used with vanilla and Stencil JavaScript pro

:::

## Catch-all Routes {/* #catch-all-routes */}

:::note

Catch-all routes are supported starting in Ionic v9.1. In earlier versions, `url="/:any"` can be used to catch paths whose first segment does not match another route. Unknown paths below a route that does match, such as `/admin/settings`, still render that route.

:::

A `url` that ends in `*` is a catch-all route. It matches any remaining path, which is useful for showing a "not found" page. The part of the path matched by `*` is passed to the component as the `pathMatch` property, without a leading `/`.

```html
<ion-router>
<ion-route url="/" component="page-home"></ion-route>
<ion-route url="/admin" component="page-admin"></ion-route>
<ion-route url="/admin/users/:id" component="page-admin-user"></ion-route>
<ion-route url="/admin/*" component="page-admin-not-found"></ion-route>
<ion-route url="*" component="page-not-found"></ion-route>
</ion-router>
```

With these routes:

- `/admin` renders `page-admin`.
- `/admin/users/1` renders `page-admin-user`.
- `/admin/settings` renders `page-admin-not-found` with `pathMatch` set to `settings`.
- `/admin/users/1/edit` renders `page-admin-not-found` with `pathMatch` set to `users/1/edit`.
- `/settings` renders `page-not-found` with `pathMatch` set to `settings`.
Comment thread
brandyscarney marked this conversation as resolved.
Outdated

The component reads `pathMatch` like any other property:

<Tabs groupId="framework" defaultValue="javascript" values={[{ value: 'javascript', label: 'Javascript' }, { value: 'stencil', label: 'Stencil' }]}>

<TabItem value="javascript">

```javascript
customElements.define(
'page-not-found',
class extends HTMLElement {
connectedCallback() {
this.innerHTML = `
<ion-content>
<p>No page found at /${this.pathMatch}</p>
</ion-content>
`;
}
}
);
```

</TabItem>

<TabItem value="stencil">

```typescript
import { Component, Prop, h } from '@stencil/core';

@Component({
tag: 'page-not-found',
})
export class PageNotFound {
@Prop() pathMatch?: string;

render() {
return (
<ion-content>
<p>No page found at /{this.pathMatch}</p>
</ion-content>
);
}
}
```

</TabItem>

</Tabs>

### Matching Priority {/* #matching-priority */}

Without a catch-all, a route that has a `url` and no child routes also matches paths that have extra segments after its `url`. Routes with an empty `url`, such as `/` or a default child route, only match exactly. If the catch-all routes above were removed, `/admin/settings` would render `page-admin`. A catch-all route always wins over these partial matches.
Comment thread
brandyscarney marked this conversation as resolved.
Outdated

When a catch-all route and a route without a catch-all both match the whole path, the route with more fixed segments wins. A fixed segment is one that is not a parameter, such as `admin`. If they have the same number, the route without the catch-all wins. For example, for `/admin/users`, `/admin/*` wins over `/:section/:id`, but loses to `/admin/:id`.
Comment thread
brandyscarney marked this conversation as resolved.
Outdated

When more than one catch-all route matches, the one with the most fixed segments wins. Segments from parent routes count toward this total, so a catch-all route nested inside another route can handle unknown paths below it.

Redirects run before routes are matched. A redirect from `*` applies to every path, so `<ion-route-redirect from="*">` takes precedence over `<ion-route url="*">`.

### Caveats {/* #caveats */}

A catch-all route also matches its own prefix, so `/admin/*` matches `/admin` with `pathMatch` set to an empty string. This differs from [`ion-route-redirect`](route-redirect.mdx), where `from="/admin/*"` does not match `/admin`.

A `*` is only treated as a wildcard when it is the last segment of the `url`. On a route with child routes, the `*` is ignored and the route matches as if its `url` did not end in `*`.

The router sets `pathMatch` on catch-all routes and overwrites any value passed in `componentProps`, so do not pass it there.

If the `component` of a catch-all route is a tab in `ion-tabs`, the tab does not receive `pathMatch`. Instead, nest the catch-all route as a child of the tab's route so it renders in that tab's `ion-router-outlet`:

```html
<ion-route url="/docs" component="tab-docs">
<ion-route component="page-docs"></ion-route>
<ion-route url="*" component="page-docs-not-found"></ion-route>
</ion-route>
```

## Navigation Hooks {/* #navigation-hooks */}

Navigation hooks can be used to perform tasks or act as navigation guards. Hooks are used by providing functions to the `beforeEnter` and `beforeLeave` properties on each `ion-route`. Returning `true` allows navigation to proceed, while returning `false` causes it to be cancelled. Returning an object of type `NavigationHookOptions` allows you to redirect navigation to another page.
Expand Down
5 changes: 5 additions & 0 deletions docs/api/router.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,12 @@ interface RouterCustomEvent extends CustomEvent {

## Usage {/* #usage */}

The last route is a [catch-all route](route.mdx#catch-all-routes) that renders `page-not-found` for any URL that no other route matches.

```html
<ion-router>
<ion-route-redirect from="/" to="/schedule"></ion-route-redirect>

<ion-route component="page-tabs">
<ion-route url="/schedule" component="tab-schedule">
<ion-route component="page-schedule"></ion-route>
Expand All @@ -100,6 +104,7 @@ interface RouterCustomEvent extends CustomEvent {
<ion-route url="/account" component="page-account"></ion-route>
<ion-route url="/signup" component="page-signup"></ion-route>
<ion-route url="/support" component="page-support"></ion-route>
<ion-route url="*" component="page-not-found"></ion-route>
</ion-router>
```

Expand Down
Loading