mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-20 12:29:55 +08:00
refactor(action-sheet): restructure action-sheet, move controller to separate module
restructure action-sheet, move controller to separate module
This commit is contained in:
@ -3,7 +3,7 @@ import { Component, ElementRef, HostListener, Renderer, ViewEncapsulation } from
|
|||||||
import { assert } from '../../util/util';
|
import { assert } from '../../util/util';
|
||||||
import { BlockerDelegate, GestureController, BLOCK_ALL } from '../../gestures/gesture-controller';
|
import { BlockerDelegate, GestureController, BLOCK_ALL } from '../../gestures/gesture-controller';
|
||||||
import { Config } from '../../config/config';
|
import { Config } from '../../config/config';
|
||||||
import { Key } from '../../platform/key';
|
import { KEY_ESCAPE } from '../../platform/key';
|
||||||
import { Platform } from '../../platform/platform';
|
import { Platform } from '../../platform/platform';
|
||||||
import { NavParams } from '../../navigation/nav-params';
|
import { NavParams } from '../../navigation/nav-params';
|
||||||
import { NavOptions } from '../../navigation/nav-util';
|
import { NavOptions } from '../../navigation/nav-util';
|
||||||
@ -135,11 +135,9 @@ export class ActionSheetCmp {
|
|||||||
|
|
||||||
@HostListener('body:keyup', ['$event'])
|
@HostListener('body:keyup', ['$event'])
|
||||||
keyUp(ev: KeyboardEvent) {
|
keyUp(ev: KeyboardEvent) {
|
||||||
if (this.enabled && this._viewCtrl.isLast()) {
|
if (this.enabled && ev.keyCode === KEY_ESCAPE && this._viewCtrl.isLast()) {
|
||||||
if (ev.keyCode === Key.ESCAPE) {
|
console.debug('actionsheet, escape button');
|
||||||
console.debug('actionsheet, escape button');
|
this.bdClick();
|
||||||
this.bdClick();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
170
src/components/action-sheet/action-sheet-controller.ts
Normal file
170
src/components/action-sheet/action-sheet-controller.ts
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
|
import { ActionSheet } from './action-sheet';
|
||||||
|
import { ActionSheetOptions } from './action-sheet-options';
|
||||||
|
import { App } from '../app/app';
|
||||||
|
import { Config } from '../../config/config';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name ActionSheetController
|
||||||
|
* @description
|
||||||
|
* An Action Sheet is a dialog that lets the user choose from a set of
|
||||||
|
* options. It appears on top of the app's content, and must be manually
|
||||||
|
* dismissed by the user before they can resume interaction with the app.
|
||||||
|
* Dangerous (destructive) options are made obvious in `ios` mode. There are easy
|
||||||
|
* ways to cancel out of the action sheet, such as tapping the backdrop or
|
||||||
|
* hitting the escape key on desktop.
|
||||||
|
*
|
||||||
|
* An action sheet is created from an array of `buttons`, with each button
|
||||||
|
* including properties for its `text`, and optionally a `handler` and `role`.
|
||||||
|
* If a handler returns `false` then the action sheet will not be dismissed. An
|
||||||
|
* action sheet can also optionally have a `title`, `subTitle` and an `icon`.
|
||||||
|
*
|
||||||
|
* A button's `role` property can either be `destructive` or `cancel`. Buttons
|
||||||
|
* without a role property will have the default look for the platform. Buttons
|
||||||
|
* with the `cancel` role will always load as the bottom button, no matter where
|
||||||
|
* they are in the array. All other buttons will be displayed in the order they
|
||||||
|
* have been added to the `buttons` array. Note: We recommend that `destructive`
|
||||||
|
* buttons are always the first button in the array, making them the top button.
|
||||||
|
* Additionally, if the action sheet is dismissed by tapping the backdrop, then
|
||||||
|
* it will fire the handler from the button with the cancel role.
|
||||||
|
*
|
||||||
|
* You can pass all of the action sheet's options in the first argument of
|
||||||
|
* the create method: `ActionSheet.create(opts)`. Otherwise the action sheet's
|
||||||
|
* instance has methods to add options, like `setTitle()` or `addButton()`.
|
||||||
|
*
|
||||||
|
* @usage
|
||||||
|
* ```ts
|
||||||
|
* import { ActionSheetController } from 'ionic-angular'
|
||||||
|
*
|
||||||
|
* export class MyClass{
|
||||||
|
*
|
||||||
|
* constructor(public actionSheetCtrl: ActionSheetController) {}
|
||||||
|
*
|
||||||
|
* presentActionSheet() {
|
||||||
|
* let actionSheet = this.actionSheetCtrl.create({
|
||||||
|
* title: 'Modify your album',
|
||||||
|
* buttons: [
|
||||||
|
* {
|
||||||
|
* text: 'Destructive',
|
||||||
|
* role: 'destructive',
|
||||||
|
* handler: () => {
|
||||||
|
* console.log('Destructive clicked');
|
||||||
|
* }
|
||||||
|
* },
|
||||||
|
* {
|
||||||
|
* text: 'Archive',
|
||||||
|
* handler: () => {
|
||||||
|
* console.log('Archive clicked');
|
||||||
|
* }
|
||||||
|
* },
|
||||||
|
* {
|
||||||
|
* text: 'Cancel',
|
||||||
|
* role: 'cancel',
|
||||||
|
* handler: () => {
|
||||||
|
* console.log('Cancel clicked');
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* ]
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* actionSheet.present();
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @advanced
|
||||||
|
*
|
||||||
|
* ActionSheet create options
|
||||||
|
*
|
||||||
|
* | Option | Type | Description |
|
||||||
|
* |-----------------------|------------|--------------------------------------------------------------------|
|
||||||
|
* | title |`string` | The title for the Action Sheet. |
|
||||||
|
* | subTitle |`string` | The sub-title for the Action Sheet. |
|
||||||
|
* | cssClass |`string` | Additional classes for custom styles, separated by spaces. |
|
||||||
|
* | enableBackdropDismiss |`boolean` | If the Action Sheet should close when the user taps the backdrop. |
|
||||||
|
* | buttons |`array<any>`| An array of buttons to display. |
|
||||||
|
*
|
||||||
|
* ActionSheet button options
|
||||||
|
*
|
||||||
|
* | Option | Type | Description |
|
||||||
|
* |----------|----------|--------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
|
* | text | `string` | The buttons text. |
|
||||||
|
* | icon | `icon` | The buttons icons. |
|
||||||
|
* | handler | `any` | An express the button should evaluate. |
|
||||||
|
* | cssClass | `string` | Additional classes for custom styles, separated by spaces. |
|
||||||
|
* | role | `string` | How the button should be displayed, `destructive` or `cancel`. If not role is provided, it will display the button without any additional styles.|
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* ### Dismissing And Async Navigation
|
||||||
|
*
|
||||||
|
* After an action sheet 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/#nav-transition-promises) section. For action sheets,
|
||||||
|
* this means it's best to wait for the action sheet to finish its transition
|
||||||
|
* out before starting a new transition on the same nav controller.
|
||||||
|
*
|
||||||
|
* In the example below, after the 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 action sheet has even finished its transition
|
||||||
|
* out. In this case, it's best to ensure the action sheet has finished its transition
|
||||||
|
* out first, *then* start the next transition.
|
||||||
|
*
|
||||||
|
* ```ts
|
||||||
|
* let actionSheet = this.actionSheetCtrl.create({
|
||||||
|
* title: 'Hello',
|
||||||
|
* buttons: [{
|
||||||
|
* text: 'Ok',
|
||||||
|
* handler: () => {
|
||||||
|
* // user has clicked the action sheet button
|
||||||
|
* // begin the action sheet's dimiss transition
|
||||||
|
* let navTransition = actionSheet.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;
|
||||||
|
* }
|
||||||
|
* }]
|
||||||
|
* });
|
||||||
|
*
|
||||||
|
* actionSheet.present();
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* It's important to note that the handler returns `false`. A feature of
|
||||||
|
* button handlers is that they automatically dismiss the action sheet when their button
|
||||||
|
* was clicked, however, we'll need more control regarding the transition. Because
|
||||||
|
* the handler returns `false`, then the action sheet does not automatically dismiss
|
||||||
|
* itself. Instead, you now have complete control of when the action sheet has finished
|
||||||
|
* transitioning, and the ability to wait for the action sheet to finish transitioning
|
||||||
|
* out before starting a new transition.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @demo /docs/v2/demos/src/action-sheet/
|
||||||
|
* @see {@link /docs/v2/components#action-sheets ActionSheet Component Docs}
|
||||||
|
*/
|
||||||
|
@Injectable()
|
||||||
|
export class ActionSheetController {
|
||||||
|
|
||||||
|
constructor(private _app: App, public config: Config) { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open an action sheet with a title, subTitle, and an array of buttons
|
||||||
|
* @param {ActionSheetOptions} opts Action sheet options
|
||||||
|
*/
|
||||||
|
create(opts: ActionSheetOptions = {}): ActionSheet {
|
||||||
|
return new ActionSheet(this._app, opts, this.config);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,25 +1,33 @@
|
|||||||
import { Injectable } from '@angular/core';
|
|
||||||
|
|
||||||
import { ActionSheetCmp } from './action-sheet-component';
|
import { ActionSheetCmp } from './action-sheet-component';
|
||||||
import { ActionSheetOptions } from './action-sheet-options';
|
import { ActionSheetOptions } from './action-sheet-options';
|
||||||
|
import { ActionSheetSlideIn, ActionSheetMdSlideIn, ActionSheetSlideOut, ActionSheetMdSlideOut, ActionSheetWpSlideIn, ActionSheetWpSlideOut } from './action-sheet-transitions';
|
||||||
import { App } from '../app/app';
|
import { App } from '../app/app';
|
||||||
|
import { Config } from '../../config/config';
|
||||||
import { isPresent } from '../../util/util';
|
import { isPresent } from '../../util/util';
|
||||||
import { NavOptions } from '../../navigation/nav-util';
|
import { NavOptions } from '../../navigation/nav-util';
|
||||||
import { ViewController } from '../../navigation/view-controller';
|
import { ViewController } from '../../navigation/view-controller';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
export class ActionSheet extends ViewController {
|
export class ActionSheet extends ViewController {
|
||||||
private _app: App;
|
private _app: App;
|
||||||
|
|
||||||
constructor(app: App, opts: ActionSheetOptions) {
|
constructor(app: App, opts: ActionSheetOptions, config: Config) {
|
||||||
opts.buttons = opts.buttons || [];
|
opts.buttons = opts.buttons || [];
|
||||||
opts.enableBackdropDismiss = isPresent(opts.enableBackdropDismiss) ? !!opts.enableBackdropDismiss : true;
|
opts.enableBackdropDismiss = isPresent(opts.enableBackdropDismiss) ? !!opts.enableBackdropDismiss : true;
|
||||||
|
|
||||||
super(ActionSheetCmp, opts, null);
|
super(ActionSheetCmp, opts, null);
|
||||||
this._app = app;
|
this._app = app;
|
||||||
this.isOverlay = true;
|
this.isOverlay = true;
|
||||||
|
|
||||||
|
config.setTransition('action-sheet-slide-in', ActionSheetSlideIn);
|
||||||
|
config.setTransition('action-sheet-slide-out', ActionSheetSlideOut);
|
||||||
|
config.setTransition('action-sheet-md-slide-in', ActionSheetMdSlideIn);
|
||||||
|
config.setTransition('action-sheet-md-slide-out', ActionSheetMdSlideOut);
|
||||||
|
config.setTransition('action-sheet-wp-slide-in', ActionSheetWpSlideIn);
|
||||||
|
config.setTransition('action-sheet-wp-slide-out', ActionSheetWpSlideOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -63,168 +71,3 @@ export class ActionSheet extends ViewController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @name ActionSheetController
|
|
||||||
* @description
|
|
||||||
* An Action Sheet is a dialog that lets the user choose from a set of
|
|
||||||
* options. It appears on top of the app's content, and must be manually
|
|
||||||
* dismissed by the user before they can resume interaction with the app.
|
|
||||||
* Dangerous (destructive) options are made obvious in `ios` mode. There are easy
|
|
||||||
* ways to cancel out of the action sheet, such as tapping the backdrop or
|
|
||||||
* hitting the escape key on desktop.
|
|
||||||
*
|
|
||||||
* An action sheet is created from an array of `buttons`, with each button
|
|
||||||
* including properties for its `text`, and optionally a `handler` and `role`.
|
|
||||||
* If a handler returns `false` then the action sheet will not be dismissed. An
|
|
||||||
* action sheet can also optionally have a `title`, `subTitle` and an `icon`.
|
|
||||||
*
|
|
||||||
* A button's `role` property can either be `destructive` or `cancel`. Buttons
|
|
||||||
* without a role property will have the default look for the platform. Buttons
|
|
||||||
* with the `cancel` role will always load as the bottom button, no matter where
|
|
||||||
* they are in the array. All other buttons will be displayed in the order they
|
|
||||||
* have been added to the `buttons` array. Note: We recommend that `destructive`
|
|
||||||
* buttons are always the first button in the array, making them the top button.
|
|
||||||
* Additionally, if the action sheet is dismissed by tapping the backdrop, then
|
|
||||||
* it will fire the handler from the button with the cancel role.
|
|
||||||
*
|
|
||||||
* You can pass all of the action sheet's options in the first argument of
|
|
||||||
* the create method: `ActionSheet.create(opts)`. Otherwise the action sheet's
|
|
||||||
* instance has methods to add options, like `setTitle()` or `addButton()`.
|
|
||||||
*
|
|
||||||
* @usage
|
|
||||||
* ```ts
|
|
||||||
* import { ActionSheetController } from 'ionic-angular'
|
|
||||||
*
|
|
||||||
* export class MyClass{
|
|
||||||
*
|
|
||||||
* constructor(public actionSheetCtrl: ActionSheetController) {}
|
|
||||||
*
|
|
||||||
* presentActionSheet() {
|
|
||||||
* let actionSheet = this.actionSheetCtrl.create({
|
|
||||||
* title: 'Modify your album',
|
|
||||||
* buttons: [
|
|
||||||
* {
|
|
||||||
* text: 'Destructive',
|
|
||||||
* role: 'destructive',
|
|
||||||
* handler: () => {
|
|
||||||
* console.log('Destructive clicked');
|
|
||||||
* }
|
|
||||||
* },
|
|
||||||
* {
|
|
||||||
* text: 'Archive',
|
|
||||||
* handler: () => {
|
|
||||||
* console.log('Archive clicked');
|
|
||||||
* }
|
|
||||||
* },
|
|
||||||
* {
|
|
||||||
* text: 'Cancel',
|
|
||||||
* role: 'cancel',
|
|
||||||
* handler: () => {
|
|
||||||
* console.log('Cancel clicked');
|
|
||||||
* }
|
|
||||||
* }
|
|
||||||
* ]
|
|
||||||
* });
|
|
||||||
*
|
|
||||||
* actionSheet.present();
|
|
||||||
* }
|
|
||||||
* }
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* @advanced
|
|
||||||
*
|
|
||||||
* ActionSheet create options
|
|
||||||
*
|
|
||||||
* | Option | Type | Description |
|
|
||||||
* |-----------------------|------------|--------------------------------------------------------------------|
|
|
||||||
* | title |`string` | The title for the Action Sheet. |
|
|
||||||
* | subTitle |`string` | The sub-title for the Action Sheet. |
|
|
||||||
* | cssClass |`string` | Additional classes for custom styles, separated by spaces. |
|
|
||||||
* | enableBackdropDismiss |`boolean` | If the Action Sheet should close when the user taps the backdrop. |
|
|
||||||
* | buttons |`array<any>`| An array of buttons to display. |
|
|
||||||
*
|
|
||||||
* ActionSheet button options
|
|
||||||
*
|
|
||||||
* | Option | Type | Description |
|
|
||||||
* |----------|----------|--------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
||||||
* | text | `string` | The buttons text. |
|
|
||||||
* | icon | `icon` | The buttons icons. |
|
|
||||||
* | handler | `any` | An express the button should evaluate. |
|
|
||||||
* | cssClass | `string` | Additional classes for custom styles, separated by spaces. |
|
|
||||||
* | role | `string` | How the button should be displayed, `destructive` or `cancel`. If not role is provided, it will display the button without any additional styles.|
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* ### Dismissing And Async Navigation
|
|
||||||
*
|
|
||||||
* After an action sheet 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/#nav-transition-promises) section. For action sheets,
|
|
||||||
* this means it's best to wait for the action sheet to finish its transition
|
|
||||||
* out before starting a new transition on the same nav controller.
|
|
||||||
*
|
|
||||||
* In the example below, after the 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 action sheet has even finished its transition
|
|
||||||
* out. In this case, it's best to ensure the action sheet has finished its transition
|
|
||||||
* out first, *then* start the next transition.
|
|
||||||
*
|
|
||||||
* ```ts
|
|
||||||
* let actionSheet = this.actionSheetCtrl.create({
|
|
||||||
* title: 'Hello',
|
|
||||||
* buttons: [{
|
|
||||||
* text: 'Ok',
|
|
||||||
* handler: () => {
|
|
||||||
* // user has clicked the action sheet button
|
|
||||||
* // begin the action sheet's dimiss transition
|
|
||||||
* let navTransition = actionSheet.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;
|
|
||||||
* }
|
|
||||||
* }]
|
|
||||||
* });
|
|
||||||
*
|
|
||||||
* actionSheet.present();
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* It's important to note that the handler returns `false`. A feature of
|
|
||||||
* button handlers is that they automatically dismiss the action sheet when their button
|
|
||||||
* was clicked, however, we'll need more control regarding the transition. Because
|
|
||||||
* the handler returns `false`, then the action sheet does not automatically dismiss
|
|
||||||
* itself. Instead, you now have complete control of when the action sheet has finished
|
|
||||||
* transitioning, and the ability to wait for the action sheet to finish transitioning
|
|
||||||
* out before starting a new transition.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @demo /docs/v2/demos/src/action-sheet/
|
|
||||||
* @see {@link /docs/v2/components#action-sheets ActionSheet Component Docs}
|
|
||||||
*/
|
|
||||||
@Injectable()
|
|
||||||
export class ActionSheetController {
|
|
||||||
|
|
||||||
constructor(private _app: App) {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Open an action sheet with a title, subTitle, and an array of buttons
|
|
||||||
* @param {ActionSheetOptions} opts Action sheet options
|
|
||||||
*/
|
|
||||||
create(opts: ActionSheetOptions = {}): ActionSheet {
|
|
||||||
return new ActionSheet(this._app, opts);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
Reference in New Issue
Block a user