mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-18 19:21:34 +08:00
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:
@ -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 -->
|
||||
|
@ -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,18 +129,13 @@ 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
|
||||
|
||||
@ -170,20 +156,6 @@ The current best practice is to provide an array of names if the app needs to us
|
||||
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 -->
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 {}
|
||||
|
@ -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);
|
||||
```
|
@ -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 |
|
||||
|
41
core/src/components/route-redirect/usage/javascript.md
Normal file
41
core/src/components/route-redirect/usage/javascript.md
Normal 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');
|
||||
```
|
@ -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 -->
|
||||
|
||||
|
@ -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 don’t 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 don’t 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
|
||||
|
@ -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'
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
```
|
||||
|
@ -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>
|
||||
```
|
@ -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
|
||||
|
||||
|
@ -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>
|
||||
```
|
Reference in New Issue
Block a user