docs(readme): move usages from readme to usage folder (#18384)

closes ionic-team/ionic-docs#664
closes ionic-team/ionic-docs#550
closes ionic-team/ionic-docs#148
This commit is contained in:
Brandy Carney
2019-05-29 17:19:42 -04:00
committed by GitHub
parent b2290a6420
commit 17ad73ace2
14 changed files with 729 additions and 395 deletions

View File

@ -1,22 +1,6 @@
# ion-alert-controller
Alert controllers programmatically control the alert component. Alerts can be created and dismissed from the alert controller. View the [Alert](../alert) documentation for a full list of options to pass upon creation.
```javascript
async function presentAlert() {
const alertController = document.querySelector('ion-alert-controller');
await alertController.componentOnReady();
const alert = await alertController.create({
header: 'Alert',
subHeader: 'Subtitle',
message: 'This is an alert message.',
buttons: ['OK']
});
return await alert.present();
}
```
Alert controllers programmatically control the alert component. Alerts can be created and dismissed by the alert controller. View the [Alert](../alert) documentation for the list of options to pass upon creation and usage information.
<!-- Auto Generated Below -->

View File

@ -1,10 +1,11 @@
# ion-datetime
Datetimes present a picker interface from the bottom of a page, making it easy for users to select
dates and times. The picker displays scrollable columns that can be used to individually select years,
months, days, hours and minute values. Datetimes are similar to the native `input` elements of type
`datetime-local`, however, Ionic's Datetime component makes it easy to display the date and time in a
preferred format, and manage the datetime values.
Datetimes present a picker interface from the bottom of a page, making it easy for
users to select dates and times. The picker displays scrollable columns that can be
used to individually select years, months, days, hours and minute values. Datetimes
are similar to the native `input` elements of type `datetime-local`, however, Ionic's
Datetime component makes it easy to display the date and time in a preferred format,
and manage the datetime values.
## Display and Picker Formats
@ -43,43 +44,33 @@ different names for the month and day.
### Display Format
The `displayFormat` input property specifies how a datetime's value should be
The `displayFormat` property specifies how a datetime's value should be
printed, as formatted text, within the datetime component.
In the following example, the display in the `<ion-datetime>` will use the
month's short name, the numerical day with a leading zero, a comma and the
four-digit year. In addition to the date, it will display the time with the
hours in the 24-hour format and the minutes. Any character can be used as a
separator. An example display using this format is: `Jun 17, 2005 11:06`.
A few examples are provided in the chart below. The formats mentioned
above can be passed in to the display format in any combination.
```html
<ion-item>
<ion-label>Date</ion-label>
<ion-datetime display-format="MMM DD, YYYY HH:mm"></ion-datetime>
</ion-item>
```
| Display Format | Example |
| ----------------------| ----------------------- |
| `M-YYYY` | `6-2005` |
| `MM/YY` | `06/05` |
| `MMM YYYY` | `Jun 2005` |
| `YYYY, MMMM` | `2005, June` |
| `MMM DD, YYYY HH:mm` | `Jun 17, 2005 11:06` |
**Important**: `ion-datetime` will always display values relative to the user's timezone.
Given a value of `09:00:00+01:00`, the datetime component will
display it as `04:00:00-04:00` for users in a `-04:00` timezone offset.
### Picker Format
The `pickerFormat` input property determines which columns should be shown in
the interface, the order of the columns, and which format to use within each
column. If the `pickerFormat` input is not provided then it will default to the
`displayFormat`.
The `pickerFormat` property determines which columns should be shown in the picker
interface, the order of the columns, and which format to use within each
column. If `pickerFormat` is not provided then it will use the value of
`displayFormat`. Refer to the chart in the [Display Format](#display-format) section
for some formatting examples.
In the following example, the display in the `<ion-datetime>` will use the
`MM/YYYY` format, such as `06/2020`. However, the picker interface will display
two columns with the month's long name, and the four-digit year.
```html
<ion-item>
<ion-label>Date</ion-label>
<ion-datetime display-format="MM/YYYY" picker-format="MMMM YYYY"></ion-datetime>
</ion-item>
```
### Datetime Data
@ -138,52 +129,33 @@ the maximum date is to the end of the current year, and the minimum date is from
the beginning of the year that was 100 years ago.
To customize the minimum and maximum datetime values, the `min` and `max`
component inputs can be provided which may make more sense for the app's
component properties can be provided which may make more sense for the app's
use-case, rather than the default of the last 100 years. Following the same IS0
8601 format listed in the table above, each component can restrict which dates
can be selected by the user. Below is an example of restricting the date
selection between the beginning of 2016, and October 31st of 2020:
can be selected by the user. By passing `2016` to the `min` property and `2020-10-31`
to the `max` property, the datetime will restrict the date selection between the
beginning of 2016, and October 31st of 2020.
```html
<ion-item>
<ion-label>Date</ion-label>
<ion-datetime display-format="MMMM YYYY" min="2016" max="2020-10-31"></ion-datetime>
</ion-item>
```
## Month Names and Day of the Week Names
At this time, there is no one-size-fits-all standard to automatically choose the
correct language/spelling for a month name, or day of the week name, depending
on the language or locale.
on the language or locale.
The good news is that there is an [Intl.DatetimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DatetimeFormat)
standard which [most browsers](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DatetimeFormat#Browser_compatibility) have adopted.
However, at this time the standard has not been fully implemented by all popular browsers
so Ionic is unavailable to take advantage of it yet.
so Ionic is unavailable to take advantage of it yet.
Additionally, Angular also provides an internationalization service, but it is still
under heavy development so Ionic does not depend on it at this time.
The current best practice is to provide an array of names if the app needs to use names other
than the default English version of month and day names. The month names and day names can be
The current best practice is to provide an array of names if the app needs to use names other
than the default English version of month and day names. The month names and day names can be
either configured at the app level, or individual `ion-datetime` level.
### Component Input Level
```html
<ion-item>
<ion-label>Período</ion-label>
<ion-datetime
display-format="DDDD MMM D, YYYY"
month-names="janeiro, fevereiro, mar\u00e7o, ..."
month-short-names="jan, fev, mar, ..."
day-names="domingo, segunda-feira, ter\u00e7a-feira, ..."
day-short-names="dom, seg, ter, ...">
</ion-datetime>
</ion-item>
```
### Advanced Datetime Validation and Manipulation
@ -197,12 +169,6 @@ subtracting 30 minutes, etc.), or even formatting data to a specific locale,
then we highly recommend using [date-fns](https://date-fns.org) to work with
dates in JavaScript.
```html
<ion-item>
<ion-label>Date</ion-label>
<ion-datetime display-format="MM/DD/YYYY"></ion-datetime>
</ion-item>
```
<!-- Auto Generated Below -->

View File

@ -5,7 +5,7 @@ An overlay that can be used to indicate activity while blocking user interaction
### Creating
Loading indicators can be created using a [Loading Controller](../loading-controller). They can be customized by passing loading options in the loading controller's create method. The spinner name should be passed in the `spinner` property. If a value is not passed to `spinner` the loading indicator will use the spinner specified by the platform.
Loading indicators can be created using a [Loading Controller](../loading-controller). They can be customized by passing loading options in the loading controller's `create()` method. The spinner name should be passed in the `spinner` property. If a value is not passed to `spinner` the loading indicator will use the spinner specified by the platform.
### Dismissing

View File

@ -5,53 +5,13 @@ A Modal is a dialog that appears on top of the app's content, and must be dismis
### Creating
Modals can be created using a [Modal Controller](../modal-controller). They can be customized by passing modal options in the modal controller's create method.
Modals can be created using a [Modal Controller](../modal-controller). They can be customized by passing modal options in the modal controller's `create()` method.
### Passing parameters
### Dismissing
When a modal is created, parameters might be passed to the newly created modal:
The modal can be dismissed after creation by calling the `dismiss()` method on the modal controller. The `onDidDismiss` function can be called to perform an action after the modal is dismissed.
```ts
// Create a modal using MyModalComponent with some initial data
const modal = await modalController.create({
component: MyModalComponent,
componentProps: {
'prop1': value,
'prop2': value2
}
});
```
Under the hood, the controller creates a new `ion-modal` and attaches the specified component to it.
It also assigns the specified `componentProps` to the component's instance:
```js
// pseudo-code
const instance = create(MyModalComponent);
instance.prop1 = value;
instance.prop2 = value2;
```
This way, your component can access the passed params, check the "Usage" section for further code example for each frameworks.
### Returning data
Modals can also return data back to the controller when they are dismissed.
```js
const modal = await modalController.create({...});
const { data } = await modal.onDidDismiss();
console.log(data);
```
```js
// Dismiss the top modal returning some data object
modalController.dismiss({
'result': value
})
```
<!-- Auto Generated Below -->
@ -64,18 +24,20 @@ modalController.dismiss({
import { Component } from '@angular/core';
import { ModalController } from '@ionic/angular';
import { ModalPage } from '../modal/modal.page';
@Component({
selector: 'modal-example',
templateUrl: 'modal-example.html',
styleUrls: ['./modal-example.css']
})
export class ModalExample {
constructor(public modalController: ModalController) {}
constructor(public modalController: ModalController) {
}
async presentModal() {
const modal = await this.modalController.create({
component: ModalPage,
componentProps: { value: 123 }
component: ModalPage
});
return await modal.present();
}
@ -89,18 +51,77 @@ import { NavParams } from '@ionic/angular';
@Component({
selector: 'modal-page',
})
export class ModalExample {
export class ModalPage {
// "value" passed in componentProps
@Input() value: number;
constructor() {
constructor(navParams: NavParams) {
// componentProps can also be accessed at construction time using NavParams
}
}
```
### Passing Data
During creation of a modal, data can be passed in through the `componentProps`. The previous example can be written to include data:
```typescript
async presentModal() {
const modal = await this.modalController.create({
component: ModalPage,
componentProps: {
'firstName': 'Douglas',
'lastName': 'Adams',
'middleInitial': 'N'
}
});
return await modal.present();
}
```
To get the data passed into the `componentProps`, either set it as an `@Input` or access it via `NavParams` on the `ModalPage`:
```typescript
export class ModalPage {
// Data passed in by componentProps
@Input() firstName: string;
@Input() lastName: string;
@Input() middleInitial: string;
constructor(navParams: NavParams) {
// componentProps can also be accessed at construction time using NavParams
console.log(navParams.get('firstName');
}
}
```
### Dismissing a Modal
A modal can be dismissed by calling the dismiss method on the modal controller and optionally passing any data from the modal.
```javascript
export class ModalPage {
...
dismiss() {
// using the injected ModalController this page
// can "dismiss" itself and optionally pass back data
this.modalCtrl.dismiss({
'dismissed': true
});
}
}
```
After being dismissed, the data can be read in through the `onWillDismiss` or `onDidDismiss` attached to the modal after creation:
```javascript
const { data } = await modal.onWillDismiss();
console.log(data);
```
#### Lazy Loading
When lazy loading a modal, it's important to note that the modal will not be loaded when it is opened, but rather when the module that imports the modal's module is loaded.
@ -116,17 +137,17 @@ import { CalendarComponent } from './calendar.component';
import { EventModalModule } from '../modals/event/event.module';
@NgModule({
declarations: [
CalendarComponent
],
imports: [
IonicModule,
CommonModule,
EventModalModule
],
exports: [
CalendarComponent
]
declarations: [
CalendarComponent
],
imports: [
IonicModule,
CommonModule,
EventModalModule
],
exports: [
CalendarComponent
]
})
export class CalendarComponentModule {}
@ -147,11 +168,16 @@ customElements.define('modal-page', class extends HTMLElement {
this.innerHTML = `
<ion-header>
<ion-toolbar>
<ion-title>Super Modal</ion-title>
<ion-title>Modal Header</ion-title>
<ion-buttons slot="primary">
<ion-button onClick="dismissModal()">
<ion-icon slot="icon-only" name="close"></ion-icon>
</ion-button>
</ion-buttons>
</ion-toolbar>
</ion-header>
<ion-content>
Content
<ion-content class="ion-padding">
Modal Content
</ion-content>`;
}
});
@ -161,14 +187,64 @@ async function presentModal() {
const modalController = document.querySelector('ion-modal-controller');
await modalController.componentOnReady();
// present the modal
// create the modal with the `modal-page` component
const modalElement = await modalController.create({
component: 'modal-page'
});
// present the modal
await modalElement.present();
}
```
### Passing Data
During creation of a modal, data can be passed in through the `componentProps`. The previous example can be written to include data:
```javascript
const modalElement = await modalController.create({
component: 'modal-page',
componentProps: {
'firstName': 'Douglas',
'lastName': 'Adams',
'middleInitial': 'N'
}
});
```
To get the data passed into the `componentProps`, query for the modal in the `modal-page`:
```js
customElements.define('modal-page', class extends HTMLElement {
connectedCallback() {
const modalElement = document.querySelector('ion-modal');
console.log(modalElement.componentProps.firstName);
...
}
}
```
### Dismissing a Modal
A modal can be dismissed by calling the dismiss method on the modal controller and optionally passing any data from the modal.
```javascript
async function dismissModal() {
await modalController.dismiss({
'dismissed': true
});
}
```
After being dismissed, the data can be read in through the `onWillDismiss` or `onDidDismiss` attached to the modal after creation:
```javascript
const { data } = await modalElement.onWillDismiss();
console.log(data);
```
### React

View File

@ -2,18 +2,20 @@
import { Component } from '@angular/core';
import { ModalController } from '@ionic/angular';
import { ModalPage } from '../modal/modal.page';
@Component({
selector: 'modal-example',
templateUrl: 'modal-example.html',
styleUrls: ['./modal-example.css']
})
export class ModalExample {
constructor(public modalController: ModalController) {}
constructor(public modalController: ModalController) {
}
async presentModal() {
const modal = await this.modalController.create({
component: ModalPage,
componentProps: { value: 123 }
component: ModalPage
});
return await modal.present();
}
@ -27,18 +29,77 @@ import { NavParams } from '@ionic/angular';
@Component({
selector: 'modal-page',
})
export class ModalExample {
export class ModalPage {
// "value" passed in componentProps
@Input() value: number;
constructor() {
constructor(navParams: NavParams) {
// componentProps can also be accessed at construction time using NavParams
}
}
```
### Passing Data
During creation of a modal, data can be passed in through the `componentProps`. The previous example can be written to include data:
```typescript
async presentModal() {
const modal = await this.modalController.create({
component: ModalPage,
componentProps: {
'firstName': 'Douglas',
'lastName': 'Adams',
'middleInitial': 'N'
}
});
return await modal.present();
}
```
To get the data passed into the `componentProps`, either set it as an `@Input` or access it via `NavParams` on the `ModalPage`:
```typescript
export class ModalPage {
// Data passed in by componentProps
@Input() firstName: string;
@Input() lastName: string;
@Input() middleInitial: string;
constructor(navParams: NavParams) {
// componentProps can also be accessed at construction time using NavParams
console.log(navParams.get('firstName');
}
}
```
### Dismissing a Modal
A modal can be dismissed by calling the dismiss method on the modal controller and optionally passing any data from the modal.
```javascript
export class ModalPage {
...
dismiss() {
// using the injected ModalController this page
// can "dismiss" itself and optionally pass back data
this.modalCtrl.dismiss({
'dismissed': true
});
}
}
```
After being dismissed, the data can be read in through the `onWillDismiss` or `onDidDismiss` attached to the modal after creation:
```javascript
const { data } = await modal.onWillDismiss();
console.log(data);
```
#### Lazy Loading
When lazy loading a modal, it's important to note that the modal will not be loaded when it is opened, but rather when the module that imports the modal's module is loaded.
@ -54,17 +115,17 @@ import { CalendarComponent } from './calendar.component';
import { EventModalModule } from '../modals/event/event.module';
@NgModule({
declarations: [
CalendarComponent
],
imports: [
IonicModule,
CommonModule,
EventModalModule
],
exports: [
CalendarComponent
]
declarations: [
CalendarComponent
],
imports: [
IonicModule,
CommonModule,
EventModalModule
],
exports: [
CalendarComponent
]
})
export class CalendarComponentModule {}

View File

@ -10,11 +10,16 @@ customElements.define('modal-page', class extends HTMLElement {
this.innerHTML = `
<ion-header>
<ion-toolbar>
<ion-title>Super Modal</ion-title>
<ion-title>Modal Header</ion-title>
<ion-buttons slot="primary">
<ion-button onClick="dismissModal()">
<ion-icon slot="icon-only" name="close"></ion-icon>
</ion-button>
</ion-buttons>
</ion-toolbar>
</ion-header>
<ion-content>
Content
<ion-content class="ion-padding">
Modal Content
</ion-content>`;
}
});
@ -24,10 +29,60 @@ async function presentModal() {
const modalController = document.querySelector('ion-modal-controller');
await modalController.componentOnReady();
// present the modal
// create the modal with the `modal-page` component
const modalElement = await modalController.create({
component: 'modal-page'
});
// present the modal
await modalElement.present();
}
```
### Passing Data
During creation of a modal, data can be passed in through the `componentProps`. The previous example can be written to include data:
```javascript
const modalElement = await modalController.create({
component: 'modal-page',
componentProps: {
'firstName': 'Douglas',
'lastName': 'Adams',
'middleInitial': 'N'
}
});
```
To get the data passed into the `componentProps`, query for the modal in the `modal-page`:
```js
customElements.define('modal-page', class extends HTMLElement {
connectedCallback() {
const modalElement = document.querySelector('ion-modal');
console.log(modalElement.componentProps.firstName);
...
}
}
```
### Dismissing a Modal
A modal can be dismissed by calling the dismiss method on the modal controller and optionally passing any data from the modal.
```javascript
async function dismissModal() {
await modalController.dismiss({
'dismissed': true
});
}
```
After being dismissed, the data can be read in through the `onWillDismiss` or `onDidDismiss` attached to the modal after creation:
```javascript
const { data } = await modalElement.onWillDismiss();
console.log(data);
```

View File

@ -1,74 +1,85 @@
# ion-route-redirect
A redirect router can only be used in the scope of `ion-router` as a direct children of it.
A route redirect can only be used with an `ion-router` as a direct child of it.
> Note: this is only meant for vanilla JavaScript project. For Angular projects, use `ion-router-outlet` and the Angular router.
> Note: this element should only be used with a vanilla JavaScript project. For Angular projects, use `ion-router-outlet` and the Angular router.
This route has only two configurable values:
The route redirect has two configurable properties:
- `from`
- `to`
Their meaning is obvious under the context of a redirection, that occurs `from` a given URL `to` another given 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.
In other for a redirection to occurs the `from` path needs to be an exact match of the navigated URL.
## Redirection evaluation
## Multiple Route Redirects
An arbitrary number of redirect routes can be defined inside an `ion-router`, but only one can match.
Also, a redirection route WILL never redirect to another redirection router, since this could lead to infinity loops.
A route redirect will never call another redirect after its own redirect, since this could lead to infinite loops.
Let's say we have this two redirection rules:
Take the following two redirects:
```html
<ion-router>
<ion-route-redirect from="/admin" to="/login"/>
<ion-route-redirect from="/login" to="/admin"/>
<ion-route-redirect from="/admin" to="/login"></ion-route-redirect>
<ion-route-redirect from="/login" to="/admin"></ion-route-redirect>
</ion-router>
```
And the user navigates to `/admin`. The router will then redirect to `/login` and stop there.
If the user navigates to `/admin` the router will redirect to `/login` and stop there. It will never evaluate more than one redirect.
It WILL NOT never evaluate more than one redirection rule in a roll.
## Examples
### Simple path
```html
<ion-route-redirect from="/admin" to="/login">
```
This route will apply (redirect) when the user navigates to: `/admin` but it will NOT apply if the user navigates to `/admin/posts`.
In order to match any subpath of admin, the wildcard character (`*`) needs to be used.
```html
<ion-route-redirect from="/admin/*" to="/login">
```
### Redirect all routes to login
Redirection routes can work as guards, since that can prevent user to navigate to areas to your application based in a given condition, for example, if the user is authenticated or not.
```tsx
{!this.isLoggedIn &&
<ion-route-redirect from="*" to="/login"/> }
```
A router can be added and removed dynamically to redirect (or guard) some routes from being accessed.
Another approach is to modify the value of `to`, since given `to` the value of `null` or `undefined` makes disables the redirection.
```tsx
<ion-route-redirect from="*" to={this.isLoggedin ? undefined : '/login'}/>
```
<!-- Auto Generated Below -->
## Usage
### Javascript
```html
<!-- Redirects when the user navigates to `/admin` but
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
any subpath of admin -->
<ion-route-redirect from="/admin/*" to="/login"></ion-route-redirect>
```
### Route Redirects as Guards
Redirection routes can work as guards to prevent users from navigating to certain areas of an application based on a given condition, such as if the user is authenticated or not.
A route redirect can be added and removed dynamically to redirect (or guard) some routes from being accessed. In the following example, all urls `*` will be redirected to the `/login` url if `isLoggedIn` is `false`.
```tsx
const isLoggedIn = false;
const router = document.querySelector('ion-router');
const routeRedirect = document.createElement('ion-route-redirect');
routeRedirect.setAttribute('from', '*');
routeRedirect.setAttribute('to', '/login');
if (!isLoggedIn) {
router.appendChild(routeRedirect);
}
```
Alternatively, the value of `to` can be modified based on a condition. In the following example, the route redirect will check if the user is logged in and redirect to the `/login` url if not.
```html
<ion-route-redirect id="tutorialRedirect" from="*"></ion-route-redirect>
```
```javascript
const isLoggedIn = false;
const routeRedirect = document.querySelector('#tutorialRedirect');
routeRedirect.setAttribute('to', isLoggedIn ? undefined : '/login');
```
## Properties
| Property | Attribute | Description | Type | Default |

View File

@ -0,0 +1,41 @@
```html
<!-- Redirects when the user navigates to `/admin` but
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
any subpath of admin -->
<ion-route-redirect from="/admin/*" to="/login"></ion-route-redirect>
```
### Route Redirects as Guards
Redirection routes can work as guards to prevent users from navigating to certain areas of an application based on a given condition, such as if the user is authenticated or not.
A route redirect can be added and removed dynamically to redirect (or guard) some routes from being accessed. In the following example, all urls `*` will be redirected to the `/login` url if `isLoggedIn` is `false`.
```tsx
const isLoggedIn = false;
const router = document.querySelector('ion-router');
const routeRedirect = document.createElement('ion-route-redirect');
routeRedirect.setAttribute('from', '*');
routeRedirect.setAttribute('to', '/login');
if (!isLoggedIn) {
router.appendChild(routeRedirect);
}
```
Alternatively, the value of `to` can be modified based on a condition. In the following example, the route redirect will check if the user is logged in and redirect to the `/login` url if not.
```html
<ion-route-redirect id="tutorialRedirect" from="*"></ion-route-redirect>
```
```javascript
const isLoggedIn = false;
const routeRedirect = document.querySelector('#tutorialRedirect');
routeRedirect.setAttribute('to', isLoggedIn ? undefined : '/login');
```

View File

@ -1,27 +1,22 @@
# ion-split-pane
SplitPane is a component that makes it possible to create multi-view layout.
Similar to iPad apps, SplitPane allows UI elements, like Menus, to be
displayed as the viewport increases.
A split pane is useful when creating multi-view layouts. It allows UI elements, like menus, to be
displayed as the viewport width increases.
If the devices screen size is below a certain size, the SplitPane will
collapse and the menu will become hidden again. This is especially useful when
creating an app that will be served over a browser or deployed through the app
store to phones and tablets.
If the device's screen width is below a certain size, the split pane will collapse and the menu will be hidden. This is ideal for creating an app that will be served in a browser and deployed through the app store to phones and tablets.
### Setting breakpoints
### Setting Breakpoints
By default, SplitPane will expand when the screen is larger than 992px.
If you want to customize this, use the `when` input. The `when` input can
accept any valid media query, as it uses `matchMedia()` underneath.
By default, the split pane will expand when the screen is larger than 992px. To customize this, pass a breakpoint in the `when` property. The `when` property can accept a boolean value, any valid media query, or one of Ionic's predefined sizes.
SplitPane also provides some predefined media queries that can be used.
```html
<!-- could be "xs", "sm", "md", "lg", or "xl" -->
<!-- can be "xs", "sm", "md", "lg", or "xl" -->
<ion-split-pane when="md"></ion-split-pane>
<!-- can be any valid media query https://developer.mozilla.org/en-US/docs/Web/CSS/Media_Queries/Using_media_queries -->
<ion-split-pane when="(min-width: 40px)"></ion-split-pane>
```
@ -33,9 +28,6 @@ SplitPane also provides some predefined media queries that can be used.
| `lg` | `(min-width: 992px)` | Show the split-pane when the min-width is 992px (default break point) |
| `xl` | `(min-width: 1200px)` | Show the split-pane when the min-width is 1200px |
You can also pass in boolean values that will trigger SplitPane when the value
or expression evaluates to true.
<!-- Auto Generated Below -->

View File

@ -3,82 +3,12 @@
Tabs are a top level navigation component to implement a tab-based navigation.
The component is a container of individual [Tab](../tab/) components.
`ion-tabs` is a styleless component that works as a router outlet in order to handle navigation.
This component does not provide any UI feedback or mechanism to switch between tabs.
In order to do so, an `ion-tab-bar` should be provided as a direct child of `ion-tabs`:
The `ion-tabs` component does not have any styling and works as a router outlet in order to handle navigation. It does not provide any UI feedback or mechanism to switch between tabs. In order to do so, an `ion-tab-bar` should be provided as a direct child of `ion-tabs`.
```html
<ion-tabs>
<ion-tab tab="home">Home Content</ion-tab>
<ion-tab tab="settings">Settings Content</ion-tab>
Both `ion-tabs` and `ion-tab-bar` can be used as standalone elements. They dont depend on each other to work, but they are usually used together in order to implement a tab-based navigation that behaves like a native app.
<ion-tab-bar slot="bottom">
The `ion-tab-bar` needs a slot defined in order to be projected to the right place in an `ion-tabs` component.
<ion-tab-button tab="home">
<ion-label>Home</ion-label>
<ion-icon name="home"></ion-icon>
<ion-badge>6</ion-badge>
</ion-tab-button>
<ion-tab-button tab="settings">
<ion-label>Settings</ion-label>
<ion-icon name="settings"></ion-icon>
</ion-tab-button>
</ion-tab-bar>
</ion-tabs>
```
Note that both `ion-tabs` and `ion-tab-bar` can be used as standalone elements. They dont depend on each other to work, but they are usually used together in order to implement a tab-based navigation that feels like a native app.
`ion-tab-bar` always needs `slot="bottom"` in order to be projected into `ion-tabs` at the right place.
## The "tab" property
Each `ion-tab-button` will activate one of the tabs when tapped.
In order to link the button to the `ion-tab` container, a matching `tab` property must be used.
```html
<ion-tab tab="settings">
[...]
<ion-tab-button tab="settings">
```
This `ion-tab-button` and `ion-tab` are now linked by the common `tab` property.
The `tab` property identifies each tab, and it has to be unique within the scope of the same `ion-tabs`. It's important to set the same property to `ion-tab` and `ion-tab-button`, even if you are only using one. e.g. You could use the `ion-tab-bar` without using `ion-tabs`. In this case you should still give each `ion-tab` the property of `tab="something"`.
### Router integration
When the ionic's router (`ion-router`) is used, the `tab` property matches the "component" of `ion-route`:
The following route within the scope of a `ion-tabs` outlet:
```html
<ion-route url="/settings-page" component="settings"></ion-route>
```
Would match the following tab:
```html
<ion-tab tab="settings" component="settings-component"></ion-tab>
```
### Angular Router integration
Using tabs with Angular's router is fairly straight forward. Here you only need to define tab which is the reference to the route.
```html
<ion-tabs>
<ion-tab-bar slot="bottom">
<ion-tab-button tab="schedule">
<ion-icon name="calendar"></ion-icon>
<ion-label>Schedule</ion-label>
</ion-tab-button>
</ion-tab-bar>
</ion-tabs>
```
<!-- Auto Generated Below -->
@ -115,6 +45,50 @@ Using tabs with Angular's router is fairly straight forward. Here you only need
```
### Router integration
When used with Angular's router the `tab` property of the `ion-tab-button` should be a reference to the route path.
```html
<ion-tabs>
<ion-tab-bar slot="bottom">
<ion-tab-button tab="schedule">
<ion-icon name="calendar"></ion-icon>
<ion-label>Schedule</ion-label>
</ion-tab-button>
</ion-tab-bar>
</ion-tabs>
```
```typescript
import { Routes } from '@angular/router';
import { TabsPage } from './tabs-page';
const routes: Routes = [
{
path: 'tabs',
component: TabsPage,
children: [
{
path: 'schedule',
children: [
{
path: '',
loadChildren: '../schedule/schedule.module#ScheduleModule'
}
]
},
{
path: '',
redirectTo: '/app/tabs/schedule',
pathMatch: 'full'
}
]
}
];
```
### Javascript
```html
@ -163,6 +137,42 @@ Using tabs with Angular's router is fairly straight forward. Here you only need
```
## Activating Tabs
Each `ion-tab-button` will activate one of the tabs when pressed. In order to link the `ion-tab-button` to the `ion-tab` container, a matching `tab` property should be set on each component.
```html
<ion-tab tab="settings">
...
</ion-tab>
<ion-tab-button tab="settings">
...
</ion-tab-button>
```
The `ion-tab-button` and `ion-tab` above are linked by the common `tab` property.
The `tab` property identifies each tab, and it has to be unique within the `ion-tabs`. It's important to always set the `tab` property on the `ion-tab` and `ion-tab-button`, even if one component is not used.
### Router integration
When used with Ionic's router (`ion-router`) the `tab` property of the `ion-tab` matches the `component` property of an `ion-route`.
The following route within the scope of an `ion-tabs` outlet:
```html
<ion-route url="/settings-page" component="settings"></ion-route>
```
will match the following tab:
```html
<ion-tab tab="settings" component="settings-component"></ion-tab>
```
### React
```tsx

View File

@ -24,3 +24,47 @@
</ion-tab-bar>
</ion-tabs>
```
### Router integration
When used with Angular's router the `tab` property of the `ion-tab-button` should be a reference to the route path.
```html
<ion-tabs>
<ion-tab-bar slot="bottom">
<ion-tab-button tab="schedule">
<ion-icon name="calendar"></ion-icon>
<ion-label>Schedule</ion-label>
</ion-tab-button>
</ion-tab-bar>
</ion-tabs>
```
```typescript
import { Routes } from '@angular/router';
import { TabsPage } from './tabs-page';
const routes: Routes = [
{
path: 'tabs',
component: TabsPage,
children: [
{
path: 'schedule',
children: [
{
path: '',
loadChildren: '../schedule/schedule.module#ScheduleModule'
}
]
},
{
path: '',
redirectTo: '/app/tabs/schedule',
pathMatch: 'full'
}
]
}
];
```

View File

@ -42,3 +42,39 @@
</ion-tabs>
```
## Activating Tabs
Each `ion-tab-button` will activate one of the tabs when pressed. In order to link the `ion-tab-button` to the `ion-tab` container, a matching `tab` property should be set on each component.
```html
<ion-tab tab="settings">
...
</ion-tab>
<ion-tab-button tab="settings">
...
</ion-tab-button>
```
The `ion-tab-button` and `ion-tab` above are linked by the common `tab` property.
The `tab` property identifies each tab, and it has to be unique within the `ion-tabs`. It's important to always set the `tab` property on the `ion-tab` and `ion-tab-button`, even if one component is not used.
### Router integration
When used with Ionic's router (`ion-router`) the `tab` property of the `ion-tab` matches the `component` property of an `ion-route`.
The following route within the scope of an `ion-tabs` outlet:
```html
<ion-route url="/settings-page" component="settings"></ion-route>
```
will match the following tab:
```html
<ion-tab tab="settings" component="settings-component"></ion-tab>
```

View File

@ -3,68 +3,16 @@
Virtual Scroll displays a virtual, "infinite" list. An array of records
is passed to the virtual scroll containing the data to create templates
for. The template created for each record, referred to as a cell, can
consist of items, headers, and footers.
For performance reasons, not every record in the list is rendered at once;
instead a small subset of records (enough to fill the viewport) are rendered
and reused as the user scrolls.
consist of items, headers, and footers. For performance reasons, not every record
in the list is rendered at once; instead a small subset of records (enough to fill the viewport)
are rendered and reused as the user scrolls.
### The Basics
The array of records should be passed to the `items` property on the `ion-virtual-scroll` element.
The data given to the `items` property must be an array. An item
template with the `*virtualItem` property is required in the `ion-virtual-scroll`.
The `*virtualItem` property can be added to any element.
```html
<ion-virtual-scroll [items]="items">
<ion-item *virtualItem="let item">
{{ item }}
</ion-item>
</ion-virtual-scroll>
```
### Section Headers and Footers
Section headers and footers are optional. They can be dynamically created
from developer-defined functions. For example, a large list of contacts
usually has a divider for each letter in the alphabet. Developers provide
their own custom function to be called on each record. The logic in the
custom function should determine whether to create the section template
and what data to provide to the template. The custom function should
return `null` if a template shouldn't be created.
```html
<ion-virtual-scroll [items]="items" [headerFn]="myHeaderFn">
<ion-item-divider *virtualHeader="let header">
{{ header }}
</ion-item-divider>
<ion-item *virtualItem="let item">
Item: {{ item }}
</ion-item>
</ion-virtual-scroll>
```
Below is an example of a custom function called on every record. It
gets passed the individual record, the record's index number,
and the entire array of records. In this example, after every 20
records a header will be inserted. So between the 19th and 20th records,
between the 39th and 40th, and so on, a `<ion-item-divider>` will
be created and the template's data will come from the function's
returned data.
```ts
myHeaderFn(record, recordIndex, records) {
if (recordIndex % 20 === 0) {
return 'Header ' + recordIndex;
}
return null;
}
```
### Approximate Widths and Heights
If the height of items in the virtual scroll are not close to the
default size of 40px, it is extremely important to provide a value for
approxItemHeight height. An exact pixel-perfect size is not necessary,
default size of `40px`, it is extremely important to provide a value for
the `approxItemHeight` property. An exact pixel-perfect size is not necessary,
but without an estimate the virtual scroll will not render correctly.
The approximate width and height of each template is used to help
@ -98,34 +46,6 @@ renders whenever it wants which could be while the user is scrolling. However,
`<ion-img>` is governed by the containing `ion-content` and does not render
images while scrolling quickly.
```html
<ion-virtual-scroll [items]="items">
<ion-item *virtualItem="let item">
<ion-avatar item-start>
<ion-img [src]="item.avatarUrl"></ion-img>
</ion-avatar>
{{ item.firstName }} {{ item.lastName }}
</ion-item>
</ion-virtual-scroll>
```
### Custom Components
If a custom component is going to be used within Virtual Scroll, it's best
to wrap it with a good old `<div>` to ensure the component is rendered
correctly. Since each custom component's implementation and internals can be
quite different, wrapping within a `<div>` is a safe way to make sure
dimensions are measured correctly.
```html
<ion-virtual-scroll [items]="items">
<div *virtualItem="let item">
<my-custom-item [item]="item">
{{ item }}
</my-custom-item>
</div>
</ion-virtual-scroll>
```
## Virtual Scroll Performance Tips
@ -190,7 +110,7 @@ dataset, so please make sure they're performant.
<ion-virtual-scroll [items]="items" approxItemHeight="320px">
<ion-card *virtualItem="let item; let itemBounds = bounds;">
<div>
<img [src]="item.imgSrc" [height]="item.imgHeight" [alt]="item.name">
<ion-img [src]="item.imgSrc" [height]="item.imgHeight" [alt]="item.name"></ion-img>
</div>
<ion-card-header>
<ion-card-title>{{ item.name }}</ion-card-title>
@ -250,6 +170,75 @@ function getImgSrc() {
let rotateImg = 0;
```
### Basic
The array of records should be passed to the `items` property on the `ion-virtual-scroll` element.
The data given to the `items` property must be an array. An item template with the `*virtualItem` property is required in the `ion-virtual-scroll`. The `*virtualItem` property can be added to any element.
```html
<ion-virtual-scroll [items]="items">
<ion-item *virtualItem="let item">
{{ item }}
</ion-item>
</ion-virtual-scroll>
```
### Section Headers and Footers
Section headers and footers are optional. They can be dynamically created
from developer-defined functions. For example, a large list of contacts
usually has a divider for each letter in the alphabet. Developers provide
their own custom function to be called on each record. The logic in the
custom function should determine whether to create the section template
and what data to provide to the template. The custom function should
return `null` if a template shouldn't be created.
```html
<ion-virtual-scroll [items]="items" [headerFn]="myHeaderFn">
<ion-item-divider *virtualHeader="let header">
{{ header }}
</ion-item-divider>
<ion-item *virtualItem="let item">
Item: {{ item }}
</ion-item>
</ion-virtual-scroll>
```
Below is an example of a custom function called on every record. It
gets passed the individual record, the record's index number,
and the entire array of records. In this example, after every 20
records a header will be inserted. So between the 19th and 20th records,
between the 39th and 40th, and so on, a `<ion-item-divider>` will
be created and the template's data will come from the function's
returned data.
```ts
myHeaderFn(record, recordIndex, records) {
if (recordIndex % 20 === 0) {
return 'Header ' + recordIndex;
}
return null;
}
```
### Custom Components
If a custom component is going to be used within Virtual Scroll, it's best
to wrap it with a `<div>` to ensure the component is rendered correctly. Since
each custom component's implementation and internals can be quite different, wrapping
within a `<div>` is a safe way to make sure dimensions are measured correctly.
```html
<ion-virtual-scroll [items]="items">
<div *virtualItem="let item">
<my-custom-item [item]="item">
{{ item }}
</my-custom-item>
</div>
</ion-virtual-scroll>
```
### React

View File

@ -3,7 +3,7 @@
<ion-virtual-scroll [items]="items" approxItemHeight="320px">
<ion-card *virtualItem="let item; let itemBounds = bounds;">
<div>
<img [src]="item.imgSrc" [height]="item.imgHeight" [alt]="item.name">
<ion-img [src]="item.imgSrc" [height]="item.imgHeight" [alt]="item.name"></ion-img>
</div>
<ion-card-header>
<ion-card-title>{{ item.name }}</ion-card-title>
@ -62,3 +62,72 @@ function getImgSrc() {
let rotateImg = 0;
```
### Basic
The array of records should be passed to the `items` property on the `ion-virtual-scroll` element.
The data given to the `items` property must be an array. An item template with the `*virtualItem` property is required in the `ion-virtual-scroll`. The `*virtualItem` property can be added to any element.
```html
<ion-virtual-scroll [items]="items">
<ion-item *virtualItem="let item">
{{ item }}
</ion-item>
</ion-virtual-scroll>
```
### Section Headers and Footers
Section headers and footers are optional. They can be dynamically created
from developer-defined functions. For example, a large list of contacts
usually has a divider for each letter in the alphabet. Developers provide
their own custom function to be called on each record. The logic in the
custom function should determine whether to create the section template
and what data to provide to the template. The custom function should
return `null` if a template shouldn't be created.
```html
<ion-virtual-scroll [items]="items" [headerFn]="myHeaderFn">
<ion-item-divider *virtualHeader="let header">
{{ header }}
</ion-item-divider>
<ion-item *virtualItem="let item">
Item: {{ item }}
</ion-item>
</ion-virtual-scroll>
```
Below is an example of a custom function called on every record. It
gets passed the individual record, the record's index number,
and the entire array of records. In this example, after every 20
records a header will be inserted. So between the 19th and 20th records,
between the 39th and 40th, and so on, a `<ion-item-divider>` will
be created and the template's data will come from the function's
returned data.
```ts
myHeaderFn(record, recordIndex, records) {
if (recordIndex % 20 === 0) {
return 'Header ' + recordIndex;
}
return null;
}
```
### Custom Components
If a custom component is going to be used within Virtual Scroll, it's best
to wrap it with a `<div>` to ensure the component is rendered correctly. Since
each custom component's implementation and internals can be quite different, wrapping
within a `<div>` is a safe way to make sure dimensions are measured correctly.
```html
<ion-virtual-scroll [items]="items">
<div *virtualItem="let item">
<my-custom-item [item]="item">
{{ item }}
</my-custom-item>
</div>
</ion-virtual-scroll>
```