UNPKG

17.3 kBJavaScriptView Raw
1import { EventEmitter, Output } from '@angular/core';
2import { isPresent } from '../util/util';
3import { STATE_DESTROYED, STATE_NEW } from './nav-util';
4import { NavParams } from './nav-params';
5/**
6 * @name ViewController
7 * @description
8 * Access various features and information about the current view.
9 * @usage
10 * ```ts
11 * import { Component } from '@angular/core';
12 * import { ViewController } from 'ionic-angular';
13 *
14 * @Component({...})
15 * export class MyPage{
16 *
17 * constructor(public viewCtrl: ViewController) {}
18 *
19 * }
20 * ```
21 */
22var ViewController = (function () {
23 function ViewController(component, data, rootCssClass) {
24 if (rootCssClass === void 0) { rootCssClass = DEFAULT_CSS_CLASS; }
25 this.component = component;
26 this._isHidden = false;
27 this._state = STATE_NEW;
28 /**
29 * Observable to be subscribed to when the current component will become active
30 * @returns {Observable} Returns an observable
31 */
32 this.willEnter = new EventEmitter();
33 /**
34 * Observable to be subscribed to when the current component has become active
35 * @returns {Observable} Returns an observable
36 */
37 this.didEnter = new EventEmitter();
38 /**
39 * Observable to be subscribed to when the current component will no longer be active
40 * @returns {Observable} Returns an observable
41 */
42 this.willLeave = new EventEmitter();
43 /**
44 * Observable to be subscribed to when the current component is no long active
45 * @returns {Observable} Returns an observable
46 */
47 this.didLeave = new EventEmitter();
48 /**
49 * Observable to be subscribed to when the current component has been destroyed
50 * @returns {Observable} Returns an observable
51 */
52 this.willUnload = new EventEmitter();
53 /**
54 * @hidden
55 */
56 this.readReady = new EventEmitter();
57 /**
58 * @hidden
59 */
60 this.writeReady = new EventEmitter();
61 /** @hidden */
62 this.isOverlay = false;
63 /** @hidden */
64 this._emitter = new EventEmitter();
65 // passed in data could be NavParams, but all we care about is its data object
66 this.data = (data instanceof NavParams ? data.data : (isPresent(data) ? data : {}));
67 this._cssClass = rootCssClass;
68 this._ts = Date.now();
69 this._bindHandler = this.handleOrientationChange.bind(this);
70 window.addEventListener('orientationchange', this._bindHandler);
71 }
72 ViewController.prototype.handleOrientationChange = function () {
73 if (this.getContent()) {
74 this.getContent().resize();
75 }
76 };
77 /**
78 * @hidden
79 */
80 ViewController.prototype.init = function (componentRef) {
81 (void 0) /* assert */;
82 this._ts = Date.now();
83 this._cmp = componentRef;
84 this.instance = this.instance || componentRef.instance;
85 this._detached = false;
86 };
87 ViewController.prototype._setNav = function (navCtrl) {
88 this._nav = navCtrl;
89 };
90 ViewController.prototype._setInstance = function (instance) {
91 this.instance = instance;
92 };
93 /**
94 * @hidden
95 */
96 ViewController.prototype.subscribe = function (generatorOrNext) {
97 return this._emitter.subscribe(generatorOrNext);
98 };
99 /**
100 * @hidden
101 */
102 ViewController.prototype.emit = function (data) {
103 this._emitter.emit(data);
104 };
105 /**
106 * Called when the current viewController has be successfully dismissed
107 */
108 ViewController.prototype.onDidDismiss = function (callback) {
109 this._onDidDismiss = callback;
110 };
111 /**
112 * Called when the current viewController will be dismissed
113 */
114 ViewController.prototype.onWillDismiss = function (callback) {
115 this._onWillDismiss = callback;
116 };
117 /**
118 * Dismiss the current viewController
119 * @param {any} [data] Data that you want to return when the viewController is dismissed.
120 * @param {any} [role ]
121 * @param {NavOptions} navOptions Options for the dismiss navigation.
122 * @returns {any} data Returns the data passed in, if any.
123 */
124 ViewController.prototype.dismiss = function (data, role, navOptions) {
125 if (navOptions === void 0) { navOptions = {}; }
126 if (!this._nav) {
127 (void 0) /* assert */;
128 return Promise.resolve(false);
129 }
130 if (this.isOverlay && !navOptions.minClickBlockDuration) {
131 // This is a Modal being dismissed so we need
132 // to add the minClickBlockDuration option
133 // for UIWebView
134 navOptions.minClickBlockDuration = 400;
135 }
136 this._dismissData = data;
137 this._dismissRole = role;
138 var options = Object.assign({}, this._leavingOpts, navOptions);
139 return this._nav.removeView(this, options).then(function () { return data; });
140 };
141 /**
142 * @hidden
143 */
144 ViewController.prototype.getNav = function () {
145 return this._nav;
146 };
147 /**
148 * @hidden
149 */
150 ViewController.prototype.getTransitionName = function (_direction) {
151 return this._nav && this._nav.config.get('pageTransition');
152 };
153 /**
154 * @hidden
155 */
156 ViewController.prototype.getNavParams = function () {
157 return new NavParams(this.data);
158 };
159 /**
160 * @hidden
161 */
162 ViewController.prototype.setLeavingOpts = function (opts) {
163 this._leavingOpts = opts;
164 };
165 /**
166 * Check to see if you can go back in the navigation stack.
167 * @returns {boolean} Returns if it's possible to go back from this Page.
168 */
169 ViewController.prototype.enableBack = function () {
170 // update if it's possible to go back from this nav item
171 if (!this._nav) {
172 return false;
173 }
174 // the previous view may exist, but if it's about to be destroyed
175 // it shouldn't be able to go back to
176 var previousItem = this._nav.getPrevious(this);
177 return !!(previousItem);
178 };
179 Object.defineProperty(ViewController.prototype, "name", {
180 /**
181 * @hidden
182 */
183 get: function () {
184 return (this.component ? this.component.name : '');
185 },
186 enumerable: true,
187 configurable: true
188 });
189 Object.defineProperty(ViewController.prototype, "index", {
190 /**
191 * Get the index of the current component in the current navigation stack.
192 * @returns {number} Returns the index of this page within its `NavController`.
193 */
194 get: function () {
195 return (this._nav ? this._nav.indexOf(this) : -1);
196 },
197 enumerable: true,
198 configurable: true
199 });
200 /**
201 * @returns {boolean} Returns if this Page is the first in the stack of pages within its NavController.
202 */
203 ViewController.prototype.isFirst = function () {
204 return (this._nav ? this._nav.first() === this : false);
205 };
206 /**
207 * @returns {boolean} Returns if this Page is the last in the stack of pages within its NavController.
208 */
209 ViewController.prototype.isLast = function () {
210 return (this._nav ? this._nav.last() === this : false);
211 };
212 /**
213 * @hidden
214 * DOM WRITE
215 */
216 ViewController.prototype._domShow = function (shouldShow, renderer) {
217 // using hidden element attribute to display:none and not render views
218 // _hidden value of '' means the hidden attribute will be added
219 // _hidden value of null means the hidden attribute will be removed
220 // doing checks to make sure we only update the DOM when actually needed
221 // if it should render, then the hidden attribute should not be on the element
222 if (this._cmp && shouldShow === this._isHidden) {
223 this._isHidden = !shouldShow;
224 var value = (shouldShow ? null : '');
225 // ******** DOM WRITE ****************
226 renderer.setElementAttribute(this.pageRef().nativeElement, 'hidden', value);
227 }
228 };
229 /**
230 * @hidden
231 */
232 ViewController.prototype.getZIndex = function () {
233 return this._zIndex;
234 };
235 /**
236 * @hidden
237 * DOM WRITE
238 */
239 ViewController.prototype._setZIndex = function (zIndex, renderer) {
240 if (zIndex !== this._zIndex) {
241 this._zIndex = zIndex;
242 var pageRef = this.pageRef();
243 if (pageRef) {
244 // ******** DOM WRITE ****************
245 renderer.setElementStyle(pageRef.nativeElement, 'z-index', zIndex);
246 }
247 }
248 };
249 /**
250 * @returns {ElementRef} Returns the Page's ElementRef.
251 */
252 ViewController.prototype.pageRef = function () {
253 return this._cmp && this._cmp.location;
254 };
255 ViewController.prototype._setContent = function (directive) {
256 this._cntDir = directive;
257 };
258 /**
259 * @returns {component} Returns the Page's Content component reference.
260 */
261 ViewController.prototype.getContent = function () {
262 return this._cntDir;
263 };
264 ViewController.prototype._setContentRef = function (elementRef) {
265 this._cntRef = elementRef;
266 };
267 /**
268 * @returns {ElementRef} Returns the Content's ElementRef.
269 */
270 ViewController.prototype.contentRef = function () {
271 return this._cntRef;
272 };
273 ViewController.prototype._setIONContent = function (content) {
274 this._setContent(content);
275 this._ionCntDir = content;
276 };
277 /**
278 * @hidden
279 */
280 ViewController.prototype.getIONContent = function () {
281 return this._ionCntDir;
282 };
283 ViewController.prototype._setIONContentRef = function (elementRef) {
284 this._setContentRef(elementRef);
285 this._ionCntRef = elementRef;
286 };
287 /**
288 * @hidden
289 */
290 ViewController.prototype.getIONContentRef = function () {
291 return this._ionCntRef;
292 };
293 ViewController.prototype._setHeader = function (directive) {
294 this._hdrDir = directive;
295 };
296 /**
297 * @hidden
298 */
299 ViewController.prototype.getHeader = function () {
300 return this._hdrDir;
301 };
302 ViewController.prototype._setFooter = function (directive) {
303 this._ftrDir = directive;
304 };
305 /**
306 * @hidden
307 */
308 ViewController.prototype.getFooter = function () {
309 return this._ftrDir;
310 };
311 ViewController.prototype._setNavbar = function (directive) {
312 this._nb = directive;
313 };
314 /**
315 * @hidden
316 */
317 ViewController.prototype.getNavbar = function () {
318 return this._nb;
319 };
320 /**
321 * Find out if the current component has a NavBar or not. Be sure
322 * to wrap this in an `ionViewWillEnter` method in order to make sure
323 * the view has rendered fully.
324 * @returns {boolean} Returns a boolean if this Page has a navbar or not.
325 */
326 ViewController.prototype.hasNavbar = function () {
327 return !!this._nb;
328 };
329 /**
330 * Change the title of the back-button. Be sure to call this
331 * after `ionViewWillEnter` to make sure the DOM has been rendered.
332 * @param {string} val Set the back button text.
333 */
334 ViewController.prototype.setBackButtonText = function (val) {
335 this._nb && this._nb.setBackButtonText(val);
336 };
337 /**
338 * Set if the back button for the current view is visible or not. Be sure to call this
339 * after `ionViewWillEnter` to make sure the DOM has been rendered.
340 * @param {boolean} Set if this Page's back button should show or not.
341 */
342 ViewController.prototype.showBackButton = function (shouldShow) {
343 if (this._nb) {
344 this._nb.hideBackButton = !shouldShow;
345 }
346 };
347 ViewController.prototype._preLoad = function () {
348 (void 0) /* assert */;
349 this._lifecycle('PreLoad');
350 };
351 /**
352 * @hidden
353 * The view has loaded. This event only happens once per view will be created.
354 * This event is fired before the component and his children have been initialized.
355 */
356 ViewController.prototype._willLoad = function () {
357 (void 0) /* assert */;
358 this._lifecycle('WillLoad');
359 };
360 /**
361 * @hidden
362 * The view has loaded. This event only happens once per view being
363 * created. If a view leaves but is cached, then this will not
364 * fire again on a subsequent viewing. This method is a good place
365 * to put your setup code for the view; however, it is not the
366 * recommended method to use when a view becomes active.
367 */
368 ViewController.prototype._didLoad = function () {
369 (void 0) /* assert */;
370 this._lifecycle('DidLoad');
371 };
372 /**
373 * @hidden
374 * The view is about to enter and become the active view.
375 */
376 ViewController.prototype._willEnter = function () {
377 this.handleOrientationChange();
378 (void 0) /* assert */;
379 if (this._detached && this._cmp) {
380 // ensure this has been re-attached to the change detector
381 this._cmp.changeDetectorRef.reattach();
382 this._detached = false;
383 }
384 this.willEnter.emit(null);
385 this._lifecycle('WillEnter');
386 };
387 /**
388 * @hidden
389 * The view has fully entered and is now the active view. This
390 * will fire, whether it was the first load or loaded from the cache.
391 */
392 ViewController.prototype._didEnter = function () {
393 (void 0) /* assert */;
394 this._nb && this._nb.didEnter();
395 this.didEnter.emit(null);
396 this._lifecycle('DidEnter');
397 };
398 /**
399 * @hidden
400 * The view is about to leave and no longer be the active view.
401 */
402 ViewController.prototype._willLeave = function (willUnload) {
403 this.willLeave.emit(null);
404 this._lifecycle('WillLeave');
405 if (willUnload && this._onWillDismiss) {
406 this._onWillDismiss(this._dismissData, this._dismissRole);
407 this._onWillDismiss = null;
408 }
409 };
410 /**
411 * @hidden
412 * The view has finished leaving and is no longer the active view. This
413 * will fire, whether it is cached or unloaded.
414 */
415 ViewController.prototype._didLeave = function () {
416 this.didLeave.emit(null);
417 this._lifecycle('DidLeave');
418 // when this is not the active page
419 // we no longer need to detect changes
420 if (!this._detached && this._cmp) {
421 this._cmp.changeDetectorRef.detach();
422 this._detached = true;
423 }
424 };
425 /**
426 * @hidden
427 */
428 ViewController.prototype._willUnload = function () {
429 this.willUnload.emit(null);
430 this._lifecycle('WillUnload');
431 this._onDidDismiss && this._onDidDismiss(this._dismissData, this._dismissRole);
432 this._onDidDismiss = null;
433 this._dismissData = null;
434 this._dismissRole = null;
435 };
436 /**
437 * @hidden
438 * DOM WRITE
439 */
440 ViewController.prototype._destroy = function (renderer) {
441 (void 0) /* assert */;
442 if (this._cmp) {
443 if (renderer) {
444 // ensure the element is cleaned up for when the view pool reuses this element
445 // ******** DOM WRITE ****************
446 var cmpEle = this._cmp.location.nativeElement;
447 renderer.setElementAttribute(cmpEle, 'class', null);
448 renderer.setElementAttribute(cmpEle, 'style', null);
449 }
450 window.removeEventListener('orientationchange', this._bindHandler);
451 // completely destroy this component. boom.
452 this._cmp.destroy();
453 }
454 this._nav = this._cmp = this.instance = this._cntDir = this._cntRef = this._leavingOpts = this._hdrDir = this._ftrDir = this._nb = this._onDidDismiss = this._onWillDismiss = null;
455 this._state = STATE_DESTROYED;
456 };
457 /**
458 * @hidden
459 */
460 ViewController.prototype._lifecycleTest = function (lifecycle) {
461 var instance = this.instance;
462 var methodName = 'ionViewCan' + lifecycle;
463 if (instance && instance[methodName]) {
464 try {
465 var result = instance[methodName]();
466 if (result instanceof Promise) {
467 return result;
468 }
469 else {
470 // Any value but explitic false, should be true
471 return Promise.resolve(result !== false);
472 }
473 }
474 catch (e) {
475 return Promise.reject(this.name + " " + methodName + " error: " + e.message);
476 }
477 }
478 return Promise.resolve(true);
479 };
480 /**
481 * @hidden
482 */
483 ViewController.prototype._lifecycle = function (lifecycle) {
484 var instance = this.instance;
485 var methodName = 'ionView' + lifecycle;
486 if (instance && instance[methodName]) {
487 instance[methodName]();
488 }
489 };
490 ViewController.propDecorators = {
491 '_emitter': [{ type: Output },],
492 };
493 return ViewController;
494}());
495export { ViewController };
496export function isViewController(viewCtrl) {
497 return !!(viewCtrl && viewCtrl._didLoad && viewCtrl._willUnload);
498}
499var DEFAULT_CSS_CLASS = 'ion-page';
500//# sourceMappingURL=view-controller.js.map
\No newline at end of file