mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-22 21:48:42 +08:00
refactor(alert): restructure alert, move controller to separate module
restructure alert, move controller to separate module
This commit is contained in:
@ -4,7 +4,7 @@ import { Config } from '../../config/config';
|
||||
import { NON_TEXT_INPUT_REGEX } from '../../util/dom';
|
||||
import { GestureController, BlockerDelegate, BLOCK_ALL } from '../../gestures/gesture-controller';
|
||||
import { isPresent, assert } from '../../util/util';
|
||||
import { Key } from '../../platform/key';
|
||||
import { KEY_ENTER, KEY_ESCAPE } from '../../platform/key';
|
||||
import { NavParams } from '../../navigation/nav-params';
|
||||
import { NavOptions } from '../../navigation/nav-util';
|
||||
import { Platform } from '../../platform/platform';
|
||||
@ -222,7 +222,7 @@ export class AlertCmp {
|
||||
@HostListener('body:keyup', ['$event'])
|
||||
keyUp(ev: KeyboardEvent) {
|
||||
if (this.enabled && this._viewCtrl.isLast()) {
|
||||
if (ev.keyCode === Key.ENTER) {
|
||||
if (ev.keyCode === KEY_ENTER) {
|
||||
if (this.lastClick + 1000 < Date.now()) {
|
||||
// do not fire this click if there recently was already a click
|
||||
// this can happen when the button has focus and used the enter
|
||||
@ -233,7 +233,7 @@ export class AlertCmp {
|
||||
this.btnClick(button);
|
||||
}
|
||||
|
||||
} else if (ev.keyCode === Key.ESCAPE) {
|
||||
} else if (ev.keyCode === KEY_ESCAPE) {
|
||||
console.debug(`alert, escape button`);
|
||||
this.bdClick();
|
||||
}
|
||||
|
233
src/components/alert/alert-controller.ts
Normal file
233
src/components/alert/alert-controller.ts
Normal file
@ -0,0 +1,233 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
import { Alert } from './alert';
|
||||
import { App } from '../app/app';
|
||||
import { AlertOptions } from './alert-options';
|
||||
import { Config } from '../../config/config';
|
||||
|
||||
/**
|
||||
* @name AlertController
|
||||
* @description
|
||||
* An Alert is a dialog that presents users with information or collects
|
||||
* information from the user using inputs. An alert appears on top
|
||||
* of the app's content, and must be manually dismissed by the user before
|
||||
* they can resume interaction with the app. It can also optionally have a
|
||||
* `title`, `subTitle` and `message`.
|
||||
*
|
||||
* You can pass all of the alert's options in the first argument of
|
||||
* the create method: `create(opts)`. Otherwise the alert's instance
|
||||
* has methods to add options, such as `setTitle()` or `addButton()`.
|
||||
*
|
||||
*
|
||||
* ### Alert Buttons
|
||||
*
|
||||
* In the array of `buttons`, each button includes properties for its `text`,
|
||||
* and optionally a `handler`. If a handler returns `false` then the alert
|
||||
* will not automatically be dismissed when the button is clicked. All
|
||||
* buttons will show up in the order they have been added to the `buttons`
|
||||
* array, from left to right. Note: The right most button (the last one in
|
||||
* the array) is the main button.
|
||||
*
|
||||
* Optionally, a `role` property can be added to a button, such as `cancel`.
|
||||
* If a `cancel` role is on one of the buttons, then if the alert is
|
||||
* dismissed by tapping the backdrop, then it will fire the handler from
|
||||
* the button with a cancel role.
|
||||
*
|
||||
*
|
||||
* ### Alert Inputs
|
||||
*
|
||||
* Alerts can also include several different inputs whose data can be passed
|
||||
* back to the app. Inputs can be used as a simple way to prompt users for
|
||||
* information. Radios, checkboxes and text inputs are all accepted, but they
|
||||
* cannot be mixed. For example, an alert could have all radio button inputs,
|
||||
* or all checkbox inputs, but the same alert cannot mix radio and checkbox
|
||||
* inputs. Do note however, different types of "text"" inputs can be mixed,
|
||||
* such as `url`, `email`, `text`, etc. If you require a complex form UI
|
||||
* which doesn't fit within the guidelines of an alert then we recommend
|
||||
* building the form within a modal instead.
|
||||
*
|
||||
*
|
||||
* @usage
|
||||
* ```ts
|
||||
* constructor(private alertCtrl: AlertController) {
|
||||
*
|
||||
* }
|
||||
*
|
||||
* presentAlert() {
|
||||
* let alert = this.alertCtrl.create({
|
||||
* title: 'Low battery',
|
||||
* subTitle: '10% of battery remaining',
|
||||
* buttons: ['Dismiss']
|
||||
* });
|
||||
* alert.present();
|
||||
* }
|
||||
*
|
||||
* presentConfirm() {
|
||||
* let alert = this.alertCtrl.create({
|
||||
* title: 'Confirm purchase',
|
||||
* message: 'Do you want to buy this book?',
|
||||
* buttons: [
|
||||
* {
|
||||
* text: 'Cancel',
|
||||
* role: 'cancel',
|
||||
* handler: () => {
|
||||
* console.log('Cancel clicked');
|
||||
* }
|
||||
* },
|
||||
* {
|
||||
* text: 'Buy',
|
||||
* handler: () => {
|
||||
* console.log('Buy clicked');
|
||||
* }
|
||||
* }
|
||||
* ]
|
||||
* });
|
||||
* alert.present();
|
||||
* }
|
||||
*
|
||||
* presentPrompt() {
|
||||
* let alert = this.alertCtrl.create({
|
||||
* title: 'Login',
|
||||
* inputs: [
|
||||
* {
|
||||
* name: 'username',
|
||||
* placeholder: 'Username'
|
||||
* },
|
||||
* {
|
||||
* name: 'password',
|
||||
* placeholder: 'Password',
|
||||
* type: 'password'
|
||||
* }
|
||||
* ],
|
||||
* buttons: [
|
||||
* {
|
||||
* text: 'Cancel',
|
||||
* role: 'cancel',
|
||||
* handler: data => {
|
||||
* console.log('Cancel clicked');
|
||||
* }
|
||||
* },
|
||||
* {
|
||||
* text: 'Login',
|
||||
* handler: data => {
|
||||
* if (User.isValid(data.username, data.password)) {
|
||||
* // logged in!
|
||||
* } else {
|
||||
* // invalid login
|
||||
* return false;
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ]
|
||||
* });
|
||||
* alert.present();
|
||||
* }
|
||||
* ```
|
||||
* @advanced
|
||||
*
|
||||
*
|
||||
* Alert options
|
||||
*
|
||||
* | Property | Type | Description |
|
||||
* |-----------------------|-----------|---------------------------------------------------------------------------|
|
||||
* | title | `string` | The title for the alert. |
|
||||
* | subTitle | `string` | The subtitle for the alert. |
|
||||
* | message | `string` | The message for the alert. |
|
||||
* | cssClass | `string` | Additional classes for custom styles, separated by spaces. |
|
||||
* | inputs | `array` | An array of inputs for the alert. See input options. |
|
||||
* | buttons | `array` | An array of buttons for the alert. See buttons options. |
|
||||
* | enableBackdropDismiss | `boolean` | Whether the alert should be dismissed by tapping the backdrop. |
|
||||
*
|
||||
*
|
||||
* Input options
|
||||
*
|
||||
* | Property | Type | Description |
|
||||
* |-------------|-----------|-----------------------------------------------------------------|
|
||||
* | type | `string` | The type the input should be: text, tel, number, etc. |
|
||||
* | name | `string` | The name for the input. |
|
||||
* | placeholder | `string` | The input's placeholder (for textual/numeric inputs) |
|
||||
* | value | `string` | The input's value. |
|
||||
* | label | `string` | The input's label (only for radio/checkbox inputs) |
|
||||
* | checked | `boolean` | Whether or not the input is checked. |
|
||||
* | id | `string` | The input's id. |
|
||||
*
|
||||
* Button options
|
||||
*
|
||||
* | Property | Type | Description |
|
||||
* |----------|----------|-----------------------------------------------------------------|
|
||||
* | text | `string` | The buttons displayed text. |
|
||||
* | handler | `any` | Emitted when the button is pressed. |
|
||||
* | cssClass | `string` | An additional CSS class for the button. |
|
||||
* | role | `string` | The buttons role, null or `cancel`. |
|
||||
*
|
||||
* ### Dismissing And Async Navigation
|
||||
*
|
||||
* After an alert has been dismissed, the app may need to also transition
|
||||
* to another page depending on the handler's logic. However, because multiple
|
||||
* transitions were fired at roughly the same time, it's difficult for the
|
||||
* nav controller to cleanly animate multiple transitions that may
|
||||
* have been kicked off asynchronously. This is further described in the
|
||||
* [`Nav Transition Promises`](../../nav/NavController) section. For alerts,
|
||||
* this means it's best to wait for the alert to finish its transition
|
||||
* out before starting a new transition on the same nav controller.
|
||||
*
|
||||
* In the example below, after the alert button has been clicked, its handler
|
||||
* waits on async operation to complete, *then* it uses `pop` to navigate
|
||||
* back a page in the same stack. The potential problem is that the async operation
|
||||
* may have been completed before the alert has even finished its transition
|
||||
* out. In this case, it's best to ensure the alert has finished its transition
|
||||
* out first, *then* start the next transition.
|
||||
*
|
||||
* ```ts
|
||||
* let alert = this.alertCtrl.create({
|
||||
* title: 'Hello',
|
||||
* buttons: [{
|
||||
* text: 'Ok',
|
||||
* handler: () => {
|
||||
* // user has clicked the alert button
|
||||
* // begin the alert's dismiss transition
|
||||
* let navTransition = alert.dismiss();
|
||||
*
|
||||
* // start some async method
|
||||
* someAsyncOperation().then(() => {
|
||||
* // once the async operation has completed
|
||||
* // then run the next nav transition after the
|
||||
* // first transition has finished animating out
|
||||
*
|
||||
* navTransition.then(() => {
|
||||
* this.nav.pop();
|
||||
* });
|
||||
* });
|
||||
* return false;
|
||||
* }
|
||||
* }]
|
||||
* });
|
||||
*
|
||||
* alert.present();
|
||||
* ```
|
||||
*
|
||||
* It's important to note that the handler returns `false`. A feature of
|
||||
* button handlers is that they automatically dismiss the alert when their button
|
||||
* was clicked, however, we'll need more control regarding the transition. Because
|
||||
* the handler returns `false`, then the alert does not automatically dismiss
|
||||
* itself. Instead, you now have complete control of when the alert has finished
|
||||
* transitioning, and the ability to wait for the alert to finish transitioning
|
||||
* out before starting a new transition.
|
||||
*
|
||||
*
|
||||
* @demo /docs/v2/demos/src/alert/
|
||||
*/
|
||||
@Injectable()
|
||||
export class AlertController {
|
||||
|
||||
constructor(private _app: App, public config: Config) { }
|
||||
|
||||
/**
|
||||
* Display an alert with a title, inputs, and buttons
|
||||
* @param {AlertOptions} opts Alert. See the table below
|
||||
*/
|
||||
create(opts: AlertOptions = {}): Alert {
|
||||
return new Alert(this._app, opts, this.config);
|
||||
}
|
||||
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
import { App } from '../app/app';
|
||||
import { AlertCmp } from './alert-component';
|
||||
import { AlertOptions, AlertInputOptions } from './alert-options';
|
||||
import { AlertPopIn, AlertPopOut, AlertMdPopIn, AlertMdPopOut, AlertWpPopIn, AlertWpPopOut } from './alert-transitions';
|
||||
import { Config } from '../../config/config';
|
||||
import { isPresent } from '../../util/util';
|
||||
import { NavOptions } from '../../navigation/nav-util';
|
||||
import { ViewController } from '../../navigation/view-controller';
|
||||
@ -14,7 +14,7 @@ import { ViewController } from '../../navigation/view-controller';
|
||||
export class Alert extends ViewController {
|
||||
private _app: App;
|
||||
|
||||
constructor(app: App, opts: AlertOptions = {}) {
|
||||
constructor(app: App, opts: AlertOptions = {}, config: Config) {
|
||||
opts.inputs = opts.inputs || [];
|
||||
opts.buttons = opts.buttons || [];
|
||||
opts.enableBackdropDismiss = isPresent(opts.enableBackdropDismiss) ? !!opts.enableBackdropDismiss : true;
|
||||
@ -22,6 +22,13 @@ export class Alert extends ViewController {
|
||||
super(AlertCmp, opts, null);
|
||||
this._app = app;
|
||||
this.isOverlay = true;
|
||||
|
||||
config.setTransition('alert-pop-in', AlertPopIn);
|
||||
config.setTransition('alert-pop-out', AlertPopOut);
|
||||
config.setTransition('alert-md-pop-in', AlertMdPopIn);
|
||||
config.setTransition('alert-md-pop-out', AlertMdPopOut);
|
||||
config.setTransition('alert-wp-pop-in', AlertWpPopIn);
|
||||
config.setTransition('alert-wp-pop-out', AlertWpPopOut);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -93,234 +100,3 @@ export class Alert extends ViewController {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @name AlertController
|
||||
* @description
|
||||
* An Alert is a dialog that presents users with information or collects
|
||||
* information from the user using inputs. An alert appears on top
|
||||
* of the app's content, and must be manually dismissed by the user before
|
||||
* they can resume interaction with the app. It can also optionally have a
|
||||
* `title`, `subTitle` and `message`.
|
||||
*
|
||||
* You can pass all of the alert's options in the first argument of
|
||||
* the create method: `create(opts)`. Otherwise the alert's instance
|
||||
* has methods to add options, such as `setTitle()` or `addButton()`.
|
||||
*
|
||||
*
|
||||
* ### Alert Buttons
|
||||
*
|
||||
* In the array of `buttons`, each button includes properties for its `text`,
|
||||
* and optionally a `handler`. If a handler returns `false` then the alert
|
||||
* will not automatically be dismissed when the button is clicked. All
|
||||
* buttons will show up in the order they have been added to the `buttons`
|
||||
* array, from left to right. Note: The right most button (the last one in
|
||||
* the array) is the main button.
|
||||
*
|
||||
* Optionally, a `role` property can be added to a button, such as `cancel`.
|
||||
* If a `cancel` role is on one of the buttons, then if the alert is
|
||||
* dismissed by tapping the backdrop, then it will fire the handler from
|
||||
* the button with a cancel role.
|
||||
*
|
||||
*
|
||||
* ### Alert Inputs
|
||||
*
|
||||
* Alerts can also include several different inputs whose data can be passed
|
||||
* back to the app. Inputs can be used as a simple way to prompt users for
|
||||
* information. Radios, checkboxes and text inputs are all accepted, but they
|
||||
* cannot be mixed. For example, an alert could have all radio button inputs,
|
||||
* or all checkbox inputs, but the same alert cannot mix radio and checkbox
|
||||
* inputs. Do note however, different types of "text"" inputs can be mixed,
|
||||
* such as `url`, `email`, `text`, etc. If you require a complex form UI
|
||||
* which doesn't fit within the guidelines of an alert then we recommend
|
||||
* building the form within a modal instead.
|
||||
*
|
||||
*
|
||||
* @usage
|
||||
* ```ts
|
||||
*
|
||||
* import { AlertController } from 'ionic-angular';
|
||||
*
|
||||
* constructor(private alertCtrl: AlertController) {
|
||||
*
|
||||
* }
|
||||
*
|
||||
* presentAlert() {
|
||||
* let alert = this.alertCtrl.create({
|
||||
* title: 'Low battery',
|
||||
* subTitle: '10% of battery remaining',
|
||||
* buttons: ['Dismiss']
|
||||
* });
|
||||
* alert.present();
|
||||
* }
|
||||
*
|
||||
* presentConfirm() {
|
||||
* let alert = this.alertCtrl.create({
|
||||
* title: 'Confirm purchase',
|
||||
* message: 'Do you want to buy this book?',
|
||||
* buttons: [
|
||||
* {
|
||||
* text: 'Cancel',
|
||||
* role: 'cancel',
|
||||
* handler: () => {
|
||||
* console.log('Cancel clicked');
|
||||
* }
|
||||
* },
|
||||
* {
|
||||
* text: 'Buy',
|
||||
* handler: () => {
|
||||
* console.log('Buy clicked');
|
||||
* }
|
||||
* }
|
||||
* ]
|
||||
* });
|
||||
* alert.present();
|
||||
* }
|
||||
*
|
||||
* presentPrompt() {
|
||||
* let alert = this.alertCtrl.create({
|
||||
* title: 'Login',
|
||||
* inputs: [
|
||||
* {
|
||||
* name: 'username',
|
||||
* placeholder: 'Username'
|
||||
* },
|
||||
* {
|
||||
* name: 'password',
|
||||
* placeholder: 'Password',
|
||||
* type: 'password'
|
||||
* }
|
||||
* ],
|
||||
* buttons: [
|
||||
* {
|
||||
* text: 'Cancel',
|
||||
* role: 'cancel',
|
||||
* handler: data => {
|
||||
* console.log('Cancel clicked');
|
||||
* }
|
||||
* },
|
||||
* {
|
||||
* text: 'Login',
|
||||
* handler: data => {
|
||||
* if (User.isValid(data.username, data.password)) {
|
||||
* // logged in!
|
||||
* } else {
|
||||
* // invalid login
|
||||
* return false;
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* ]
|
||||
* });
|
||||
* alert.present();
|
||||
* }
|
||||
* ```
|
||||
* @advanced
|
||||
*
|
||||
*
|
||||
* Alert options
|
||||
*
|
||||
* | Property | Type | Description |
|
||||
* |-----------------------|-----------|---------------------------------------------------------------------------|
|
||||
* | title | `string` | The title for the alert. |
|
||||
* | subTitle | `string` | The subtitle for the alert. |
|
||||
* | message | `string` | The message for the alert. |
|
||||
* | cssClass | `string` | Additional classes for custom styles, separated by spaces. |
|
||||
* | mode | `string` | Set alert mode (ios, md, wp). |
|
||||
* | inputs | `array` | An array of inputs for the alert. See input options. |
|
||||
* | buttons | `array` | An array of buttons for the alert. See buttons options. |
|
||||
* | enableBackdropDismiss | `boolean` | Whether the alert should be dismissed by tapping the backdrop. |
|
||||
*
|
||||
*
|
||||
* Input options
|
||||
*
|
||||
* | Property | Type | Description |
|
||||
* |-------------|-----------|-----------------------------------------------------------------|
|
||||
* | type | `string` | The type the input should be: text, tel, number, etc. |
|
||||
* | name | `string` | The name for the input. |
|
||||
* | placeholder | `string` | The input's placeholder (for textual/numeric inputs) |
|
||||
* | value | `string` | The input's value. |
|
||||
* | label | `string` | The input's label (only for radio/checkbox inputs) |
|
||||
* | checked | `boolean` | Whether or not the input is checked. |
|
||||
* | id | `string` | The input's id. |
|
||||
*
|
||||
* Button options
|
||||
*
|
||||
* | Property | Type | Description |
|
||||
* |----------|----------|-----------------------------------------------------------------|
|
||||
* | text | `string` | The buttons displayed text. |
|
||||
* | handler | `any` | Emitted when the button is pressed. |
|
||||
* | cssClass | `string` | An additional CSS class for the button. |
|
||||
* | role | `string` | The buttons role, null or `cancel`. |
|
||||
*
|
||||
* ### Dismissing And Async Navigation
|
||||
*
|
||||
* After an alert has been dismissed, the app may need to also transition
|
||||
* to another page depending on the handler's logic. However, because multiple
|
||||
* transitions were fired at roughly the same time, it's difficult for the
|
||||
* nav controller to cleanly animate multiple transitions that may
|
||||
* have been kicked off asynchronously. This is further described in the
|
||||
* [`Nav Transition Promises`](../../nav/NavController) section. For alerts,
|
||||
* this means it's best to wait for the alert to finish its transition
|
||||
* out before starting a new transition on the same nav controller.
|
||||
*
|
||||
* In the example below, after the alert button has been clicked, its handler
|
||||
* waits on async operation to complete, *then* it uses `pop` to navigate
|
||||
* back a page in the same stack. The potential problem is that the async operation
|
||||
* may have been completed before the alert has even finished its transition
|
||||
* out. In this case, it's best to ensure the alert has finished its transition
|
||||
* out first, *then* start the next transition.
|
||||
*
|
||||
* ```ts
|
||||
* let alert = this.alertCtrl.create({
|
||||
* title: 'Hello',
|
||||
* buttons: [{
|
||||
* text: 'Ok',
|
||||
* handler: () => {
|
||||
* // user has clicked the alert button
|
||||
* // begin the alert's dismiss transition
|
||||
* let navTransition = alert.dismiss();
|
||||
*
|
||||
* // start some async method
|
||||
* someAsyncOperation().then(() => {
|
||||
* // once the async operation has completed
|
||||
* // then run the next nav transition after the
|
||||
* // first transition has finished animating out
|
||||
*
|
||||
* navTransition.then(() => {
|
||||
* this.nav.pop();
|
||||
* });
|
||||
* });
|
||||
* return false;
|
||||
* }
|
||||
* }]
|
||||
* });
|
||||
*
|
||||
* alert.present();
|
||||
* ```
|
||||
*
|
||||
* It's important to note that the handler returns `false`. A feature of
|
||||
* button handlers is that they automatically dismiss the alert when their button
|
||||
* was clicked, however, we'll need more control regarding the transition. Because
|
||||
* the handler returns `false`, then the alert does not automatically dismiss
|
||||
* itself. Instead, you now have complete control of when the alert has finished
|
||||
* transitioning, and the ability to wait for the alert to finish transitioning
|
||||
* out before starting a new transition.
|
||||
*
|
||||
*
|
||||
* @demo /docs/v2/demos/src/alert/
|
||||
*/
|
||||
@Injectable()
|
||||
export class AlertController {
|
||||
|
||||
constructor(private _app: App) {}
|
||||
/**
|
||||
* Display an alert with a title, inputs, and buttons
|
||||
* @param {AlertOptions} opts Alert. See the table below
|
||||
*/
|
||||
create(opts: AlertOptions = {}): Alert {
|
||||
return new Alert(this._app, opts);
|
||||
}
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user