IonicPage
The Ionic Page handles registering and displaying specific pages based on URLs. It's used
underneath NavController
so it will never have to be interacted with directly. When a new
page is pushed with NavController
, the URL is updated to match the path to this page.
Unlike traditional web apps, URLs don't dictate navigation in Ionic apps.
Instead, URLs help us link to specific pieces of content as a breadcrumb.
The current URL gets updated as we navigate, but we use the NavController
push and pop, or NavPush
and NavPop
to move around. This makes it much easier
to handle complicated nested navigation.
We refer to our URL system as a deep link system instead of a router to encourage Ionic developers to think of URLs as a breadcrumb rather than as the source of truth in navigation. This encourages flexible navigation design and happy apps all over the world.
Usage
The first step to setting up deep links is to add the page that should be
a deep link in the IonicPageModule.forChild
import of the page's module.
For our examples, this will be MyPage
:
@NgModule({
declarations: [
MyPage
],
imports: [
IonicPageModule.forChild(MyPage)
],
entryComponents: [
MyPage
]
})
export class MyPageModule {}
Then, add the @IonicPage
decorator to the component. The most simple usage is adding an
empty decorator:
@IonicPage()
@Component({
templateUrl: 'main.html'
})
export class MyPage {}
This will automatically create a link to the MyPage
component using the same name as the class,
name
: 'MyPage'
. The page can now be navigated to by using this name. For example:
@Component({
templateUrl: 'another-page.html'
})
export class AnotherPage {
constructor(public navCtrl: NavController) {}
goToMyPage() {
// go to the MyPage component
this.navCtrl.push('MyPage');
}
}
The @IonicPage
decorator accepts a DeepLinkMetadataType
object. This object accepts
the following properties: name
, segment
, defaultHistory
, and priority
. All of them
are optional but can be used to create complex navigation links. The name
and segment
values must be unique.
Changing Name
As mentioned previously, the name
property will be set to the class name if it isn't provided.
Changing the name of the link is extremely simple. To change the name used to link to the
component, simply pass it in the decorator like so:
@IonicPage({
name: 'my-page'
})
This will create a link to the MyPage
component using the name 'my-page'
. Similar to the previous
example, the page can be navigated to by using the name:
goToMyPage() {
// go to the MyPage component
this.navCtrl.push('my-page');
}
Setting URL Path
The segment
property is used to set the URL to the page. If this property isn't provided, the
segment
will use the value of source file name without the extension ('my-page.ts'
results
in segment name 'my-page'
). Since components can be loaded anywhere in the app, the segment
doesn't require a full URL path. When a page becomes the active page, the segment
is appended
to the URL.
The segment
can be changed to anything and doesn't have to match the name
. For example, passing
a value for name
and segment
:
@IonicPage({
name: 'my-page',
segment: 'some-path'
})
When navigating to this page as the first page in the app, the URL will look something like:
http://localhost:8101/#/some-path
However, navigating to the page will still use the name
like the previous examples do.
Dynamic Links
The segment
property is useful for creating dynamic links. Sometimes the URL isn't known ahead
of time, so it can be passed as a variable.
Since passing data around is common practice in an app, it can be reflected in the app's URL by
using the :param
syntax. For example, set the segment
in the @IonicPage
decorator:
@IonicPage({
name: 'detail-page',
segment: 'detail/:id'
})
In this case, when we push
to a new instance of 'detail-page'
, the value of id
will
in the detailInfo
data being passed to push
will replace :id
in the URL.
Important: The property needs to be something that can be converted into a string, objects are not supported.
For example, to push the 'detail-page'
in the ListPage
component, the following code could
be used:
@IonicPage({
name: 'list'
})
export class ListPage {
constructor(public navCtrl: NavController) {}
pushPage(detailInfo) {
// Push an `id` to the `'detail-page'`
this.navCtrl.push('detail-page', {
'id': detailInfo.id
})
}
}
If the value of detailInfo.id
is 12
, for example, the URL would end up looking like this:
http://localhost:8101/#/list/detail/12
Since this id
will be used to pull in the data of the specific detail page, it's Important
that the id
is unique.
Note: Even though the name
is detail-page
, the segment
uses detail/:id
, and the URL
will use the segment
.
Default History
Pages can be navigated to using deep links from anywhere in the app, but sometimes the app is launched from a URL and the page needs to have the same history as if it were navigated to from inside of the app.
By default, the page would be navigated to as the first page in the stack with no prior history. A good example is the App Store on iOS. Clicking on a URL to an application in the App Store will load the details of the application with no back button, as if it were the first page ever viewed.
The default history of any page can be set in the defaultHistory
property. This history will only
be used if the history doesn't already exist, meaning if you navigate to the page the history will
be the pages that were navigated from.
The defaultHistory
property takes an array of page names. The page names are specified as statically
analyzable strings (which means you must use strings and not variables or delared constants). If the
parent page does not have a name
specified in its IonicPage
decorator its name is its class name.
For example, setting the history of the detail page to the list page where the name
is list
:
@IonicPage({
name: 'detail-page',
segment: 'detail/:id',
defaultHistory: ['list']
})
In this example, if the app is launched at http://localhost:8101/#/detail/my-detail
the displayed page
will be the 'detail-page'
with an id of my-detail
and it will show a back button that goes back to
the 'list'
page.
For a deeper example:
@IonicPage({
segment: 'contact-more-info',
defaultHistory: ['ContactDetailPage', 'Contact']
})
...
export class ContactMoreInfoPage {
...
}
In this example, if the app is launched at http://localhost:8101/#/contact/contact-more-info
the displayed page
will be the 'ContactMoreInfoPage'
. It will show a back button that will go to the 'ContactDetailPage'
which
will also show a back button which will go to the 'Contact'
page.
An example of an application with a set history stack is the Instagram application. Opening a link to an image on Instagram will show the details for that image with a back button to the user's profile page. There is no "right" way of setting the history for a page, it is up to the application.
Priority
The priority
property is only used during preloading. By default, preloading is turned off so setting
this property would do nothing. Preloading eagerly loads all deep links after the application boots
instead of on demand as needed. To enable preloading, set preloadModules
in the main application module
config to true
:
@NgModule({
declarations: [
MyApp
],
imports: [
BrowserModule,
IonicModule.forRoot(MyApp, {
preloadModules: true
})
],
bootstrap: [IonicApp],
entryComponents: [
MyApp
]
})
export class AppModule { }
If preloading is turned on, it will load the modules based on the value of priority
. The following
values are possible for priority
: "high"
, "low"
, and "off"
. When there is no priority
, it
will be set to "low"
.
All deep links with their priority set to "high"
will be loaded first. Upon completion of loading the
"high"
priority modules, all deep links with a priority of "low"
(or no priority) will be loaded. If
the priority is set to "off"
the link will not be preloaded. Setting the priority
is as simple as
passing it to the @IonicPage
decorator:
@IonicPage({
name: 'my-page',
priority: 'high'
})
We recommend setting the priority
to "high"
on the pages that will be viewed first when launching
the application.