Skip to content

Commit 2d7923b

Browse files
michaeltintiucgrgur
authored andcommitted
Refactor Ionic API, add missing bindings (#26)
* Refactor Ionic API, add missing bindings * Add tests, remove unneeded setters * Remove ion-nav support * Remove unused wrapper arg, move cache prop out of api instance
1 parent 95a1531 commit 2d7923b

File tree

7 files changed

+286
-142
lines changed

7 files changed

+286
-142
lines changed

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,6 @@ It is an extension of the Vue Router thus it can be used as a drop-in replacemen
9494
- [Basic routing](cookbook/index.html)
9595
- [Named views](cookbook/named-views.html)
9696
- [Named views with transitions](cookbook/named-views-transitions.html)
97-
- [IonNav routing](cookbook/ion-nav-routing.html)
9897
- [Custom transitions](cookbook/custom-transitions.html)
9998
- [Mix Ionic and custom transitions](cookbook/mixed-transitions.html)
10099

cookbook/ion-nav-routing.html

Lines changed: 0 additions & 80 deletions
This file was deleted.

src/api-utils.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { Delegate } from './framework-delegate'
2+
3+
// A proxy method that initializes the controller and calls requested method
4+
export function proxyMethod(tag, method, ...opts) {
5+
return initController(tag).then(ctrl => ctrl[method].apply(ctrl, opts))
6+
}
7+
8+
// Initialize an Ionic controller and append it to DOM
9+
export function initController(tag) {
10+
const element = getOrAppendElement(tag)
11+
12+
// Set the framework-specific implementations for Ionic's internals
13+
element.delegate = Delegate
14+
15+
// Return a Promise
16+
return element.componentOnReady()
17+
}
18+
19+
// Return existing Element (tag) or create a new one
20+
function getOrAppendElement(tag) {
21+
let element = document.querySelector(tag)
22+
23+
if (element) {
24+
return element
25+
}
26+
27+
return document.body.appendChild(document.createElement(tag))
28+
}

src/api.js

Lines changed: 54 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,75 +1,76 @@
1-
import { Delegate } from './framework-delegate'
1+
import ProxyController from './proxy-controller'
2+
import ProxyMenuController from './proxy-menu-controller'
23

3-
const api = {
4-
// Create or return a NavController instance and set root to a Vue component
5-
newNavController(root) {
6-
return Promise.resolve(
7-
initComponent('ion-nav', 'ion-app').then(ctrl => {
8-
ctrl.root = root
9-
return ctrl
10-
})
11-
)
12-
},
13-
// Create or return an AlertController instance and set it's properties
14-
newAlertController(props) {
15-
return this.newAbstractController('ion-alert-controller', props)
16-
},
17-
// Create or return a LoadingController instance and set it's properties
18-
newLoadingController(props) {
19-
return this.newAbstractController('ion-loading-controller', props)
20-
},
21-
// Create or return a ModalController instance and set it's properties
22-
newModalController(props) {
23-
return this.newAbstractController('ion-modal-controller', props)
24-
},
25-
// Initialize an Ionic component and set it's properties
26-
newAbstractController(tag, props) {
27-
const controller = initComponent(tag).then(ctrl => ctrl.create(props))
28-
return Promise.resolve(controller)
29-
},
4+
export default class Api {
5+
// Create or return a ActionSheetController instance
6+
get actionSheetController() {
7+
return getOrCreateController('_actionSheetController', 'ion-action-sheet-controller')
8+
}
9+
10+
// Create or return an AlertController instance
11+
get alertController() {
12+
return getOrCreateController('_alertController', 'ion-alert-controller')
13+
}
14+
15+
// Create or return a LoadingController instance
16+
get loadingController() {
17+
return getOrCreateController('_loadingController', 'ion-loading-controller')
18+
}
19+
20+
// Create or return a MenuController instance
21+
get menuController() {
22+
return getOrCreateController('_menuController', 'ion-menu-controller', ProxyMenuController)
23+
}
24+
25+
// Create or return a ModalController instance
26+
get modalController() {
27+
return getOrCreateController('_modalController', 'ion-modal-controller')
28+
}
29+
30+
// Create or return a PopoverController instance
31+
get popoverController() {
32+
return getOrCreateController('_popoverController', 'ion-popover-controller')
33+
}
34+
35+
// Create or return a ToastController instance
36+
get toastController() {
37+
return getOrCreateController('_toastController', 'ion-toast-controller')
38+
}
3039
}
3140

32-
export default api
41+
// Cached controllers
42+
Api._actionSheetController = null
43+
Api._alertController = null
44+
Api._loadingController = null
45+
Api._menuController = null
46+
Api._modalController = null
47+
Api._popoverController = null
48+
Api._toastController = null
3349

34-
api.install = function(Vue) {
50+
Api.install = function(Vue) {
3551
// If installed - skip
36-
if (api.install.installed) {
52+
if (Api.install.installed) {
3753
return
3854
}
3955

40-
api.install.installed = true
56+
Api.install.installed = true
4157

4258
// Ignore Ionic custom elements
4359
Vue.config.ignoredElements.push(/^ion-/)
4460

4561
// Give access to the API methods
4662
Object.defineProperty(Vue.prototype, '$ionic', {
4763
get() {
48-
return api
64+
return new Api()
4965
},
5066
})
5167
}
5268

53-
// Initialize an Ionic component and append it to DOM
54-
function initComponent(tag, wrapper = 'body') {
55-
// If wrapper doesn't exist use body as fall-back
56-
const wrapperEl = document.querySelector(wrapper) || document.body
57-
const element = getOrAppendElement(tag, wrapperEl)
58-
59-
// Set the framework-specific implementations for Ionic's internals
60-
element.delegate = Delegate
61-
62-
// Return a Promise
63-
return element.componentOnReady()
64-
}
65-
66-
// Return existing Element (tag) or create a new one
67-
function getOrAppendElement(tag, wrapper) {
68-
let element = document.querySelector(tag)
69-
70-
if (element) {
71-
return element
69+
// Get existing controller instance or initialize a new one
70+
function getOrCreateController(cache, tag, proxy = ProxyController) {
71+
if (!Api[cache]) {
72+
Api[cache] = new proxy(tag)
7273
}
7374

74-
return wrapper.appendChild(document.createElement(tag))
75+
return Api[cache]
7576
}

src/proxy-controller.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import * as apiUtils from './api-utils'
2+
3+
// A proxy class that allows early access to controller methods
4+
export default class ProxyController {
5+
constructor(tag) {
6+
this.tag = tag
7+
}
8+
9+
create(opts) {
10+
return apiUtils.proxyMethod(this.tag, 'create', opts)
11+
}
12+
13+
dismiss() {
14+
return apiUtils.proxyMethod(this.tag, 'dismiss')
15+
}
16+
17+
getTop() {
18+
return apiUtils.proxyMethod(this.tag, 'getTop')
19+
}
20+
}

src/proxy-menu-controller.js

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import * as apiUtils from './api-utils'
2+
3+
// A proxy class that allows early access to controller methods
4+
export default class ProxyMenuController {
5+
constructor(tag) {
6+
this.tag = tag
7+
}
8+
9+
// Open a menu
10+
open(menuId) {
11+
return apiUtils.proxyMethod(this.tag, 'open', menuId)
12+
}
13+
14+
// Close a menu
15+
close(menuId) {
16+
return apiUtils.proxyMethod(this.tag, 'close', menuId)
17+
}
18+
19+
// Toggle a menu
20+
toggle(menuId) {
21+
return apiUtils.proxyMethod(this.tag, 'toggle', menuId)
22+
}
23+
24+
// Enable or disable a menu
25+
enable(shouldEnable, menuId) {
26+
return apiUtils.proxyMethod(this.tag, 'enable', shouldEnable, menuId)
27+
}
28+
29+
// Enable or disable the ability to swipe open the menu
30+
swipeEnable(shouldEnable, menuId) {
31+
return apiUtils.proxyMethod(this.tag, 'swipeEnable', shouldEnable, menuId)
32+
}
33+
34+
// Check if specific or any menu is open
35+
isOpen(menuId) {
36+
return apiUtils.proxyMethod(this.tag, 'isOpen', menuId)
37+
}
38+
39+
// Check is certain menu is enabled
40+
isEnabled(menuId) {
41+
return apiUtils.proxyMethod(this.tag, 'isEnabled', menuId)
42+
}
43+
44+
// Get specific or first menu instance
45+
get(menuId) {
46+
return apiUtils.proxyMethod(this.tag, 'get', menuId)
47+
}
48+
49+
// Get an instance of an open menu
50+
getOpen() {
51+
return apiUtils.proxyMethod(this.tag, 'getOpen')
52+
}
53+
54+
// Get an array of all menus
55+
getMenus() {
56+
return apiUtils.proxyMethod(this.tag, 'getMenus')
57+
}
58+
}

0 commit comments

Comments
 (0)