diff --git a/ionic/components/action-sheet/action-sheet.ts b/ionic/components/action-sheet/action-sheet.ts index d1a8f7b6ff9..20e54b70e38 100644 --- a/ionic/components/action-sheet/action-sheet.ts +++ b/ionic/components/action-sheet/action-sheet.ts @@ -5,7 +5,7 @@ import {Animation} from '../../animations/animation'; import {Transition, TransitionOptions} from '../../transitions/transition'; import {Config} from '../../config/config'; import {Icon} from '../icon/icon'; -import {isDefined} from '../../util/util'; +import {isPresent} from '../../util/util'; import {NavParams} from '../nav/nav-params'; import {ViewController} from '../nav/view-controller'; @@ -82,7 +82,7 @@ export class ActionSheet extends ViewController { constructor(opts: ActionSheetOptions = {}) { opts.buttons = opts.buttons || []; - opts.enableBackdropDismiss = isDefined(opts.enableBackdropDismiss) ? !!opts.enableBackdropDismiss : true; + opts.enableBackdropDismiss = isPresent(opts.enableBackdropDismiss) ? !!opts.enableBackdropDismiss : true; super(ActionSheetCmp, opts); this.viewType = 'action-sheet'; diff --git a/ionic/components/alert/alert.ts b/ionic/components/alert/alert.ts index 514607ccda7..542f10e3242 100644 --- a/ionic/components/alert/alert.ts +++ b/ionic/components/alert/alert.ts @@ -4,7 +4,7 @@ import {NgClass, NgSwitch, NgIf, NgFor} from 'angular2/common'; import {Animation} from '../../animations/animation'; import {Transition, TransitionOptions} from '../../transitions/transition'; import {Config} from '../../config/config'; -import {isDefined} from '../../util/util'; +import {isPresent} from '../../util/util'; import {NavParams} from '../nav/nav-params'; import {ViewController} from '../nav/view-controller'; @@ -122,7 +122,7 @@ export class Alert extends ViewController { constructor(opts: AlertOptions = {}) { opts.inputs = opts.inputs || []; opts.buttons = opts.buttons || []; - opts.enableBackdropDismiss = isDefined(opts.enableBackdropDismiss) ? !!opts.enableBackdropDismiss : true; + opts.enableBackdropDismiss = isPresent(opts.enableBackdropDismiss) ? !!opts.enableBackdropDismiss : true; super(AlertCmp, opts); this.viewType = 'alert'; @@ -326,9 +326,9 @@ class AlertCmp { data.inputs = data.inputs.map((input, index) => { return { type: input.type || 'text', - name: isDefined(input.name) ? input.name : index, - placeholder: isDefined(input.placeholder) ? input.placeholder : '', - value: isDefined(input.value) ? input.value : '', + name: isPresent(input.name) ? input.name : index, + placeholder: isPresent(input.placeholder) ? input.placeholder : '', + value: isPresent(input.value) ? input.value : '', label: input.label, checked: !!input.checked, id: 'alert-input-' + this.id + '-' + index diff --git a/ionic/components/list/list.ts b/ionic/components/list/list.ts index 0089a5285fe..971d9acb75d 100644 --- a/ionic/components/list/list.ts +++ b/ionic/components/list/list.ts @@ -2,7 +2,6 @@ import {Directive, ElementRef, Renderer, Attribute, NgZone} from 'angular2/core' import {Ion} from '../ion'; import {ItemSlidingGesture} from '../item/item-sliding-gesture'; -import {isDefined} from '../../util'; /** * The List is a widely used interface element in almost any mobile app, diff --git a/ionic/components/nav/nav-controller.ts b/ionic/components/nav/nav-controller.ts index 340654d358e..8abfdd766d8 100644 --- a/ionic/components/nav/nav-controller.ts +++ b/ionic/components/nav/nav-controller.ts @@ -7,7 +7,7 @@ import {IonicApp} from '../app/app'; import {Keyboard} from '../../util/keyboard'; import {NavParams} from './nav-params'; import {NavRouter} from './nav-router'; -import {pascalCaseToDashCase, isTrueProperty, isUndefined} from '../../util/util'; +import {pascalCaseToDashCase, isTrueProperty, isBlank} from '../../util/util'; import {raf} from '../../util/dom'; import {SwipeBackGesture} from './swipe-back'; import {Transition} from '../../transitions/transition'; @@ -178,7 +178,7 @@ export class NavController extends Ion { * @param {object} [opts={}] Any options you want to use pass to transtion * @returns {Promise} Returns a promise when done */ - setRoot(page: Type, params: any = {}, opts: NavOptions = {}): Promise { + setRoot(page: Type, params?: any, opts?: NavOptions): Promise { return this.setPages([{page, params}], opts); } @@ -255,11 +255,15 @@ export class NavController extends Ion { * @param {object} [opts={}] Any options you want to use pass * @returns {Promise} Returns a promise when the pages are set */ - setPages(pages: Array<{page: Type, params?: any}>, opts: NavOptions = {}): Promise { + setPages(pages: Array<{page: Type, params?: any}>, opts?: NavOptions): Promise { if (!pages || !pages.length) { return Promise.resolve(false); } + if (isBlank(opts)) { + opts = {}; + } + // deprecated warning pages.forEach(pg => { if (pg['componentType']) { @@ -303,7 +307,7 @@ export class NavController extends Ion { /** * @private */ - private setViews(components, opts: NavOptions = {}) { + private setViews(components, opts?: NavOptions) { console.warn('setViews() deprecated, use setPages() instead'); return this.setPages(components, opts); } @@ -373,7 +377,7 @@ export class NavController extends Ion { * @param {object} [opts={}] Any options you want to use pass to transtion * @returns {Promise} Returns a promise, which resolves when the transition has completed */ - push(page: Type, params: any = {}, opts: NavOptions = {}) { + push(page: Type, params?: any, opts?: NavOptions) { return this.insertPages(-1, [{page: page, params: params}], opts); } @@ -402,7 +406,7 @@ export class NavController extends Ion { * @param {object} [opts={}] Any options you want to use pass to transtion * @returns {Promise} Returns a promise, which resolves when the transition has completed */ - present(enteringView: ViewController, opts: NavOptions = {}): Promise { + present(enteringView: ViewController, opts?: NavOptions): Promise { let rootNav = this.rootNav; if (rootNav['_tabs']) { @@ -412,6 +416,10 @@ export class NavController extends Ion { return; } + if (isBlank(opts)) { + opts = {}; + } + enteringView.setNav(rootNav); opts.keyboardClose = false; @@ -454,7 +462,7 @@ export class NavController extends Ion { * @param {object} [opts={}] Any options you want to use pass to transtion * @returns {Promise} Returns a promise when the page has been inserted into the navigation stack */ - insert(insertIndex: number, page: Type, params: any = {}, opts: NavOptions = {}): Promise { + insert(insertIndex: number, page: Type, params?: any, opts?: NavOptions): Promise { return this.insertPages(insertIndex, [{page: page, params: params}], opts); } @@ -486,16 +494,20 @@ export class NavController extends Ion { * @param {object} [opts={}] Any options you want to use pass to transtion * @returns {Promise} Returns a promise when the pages have been inserted into the navigation stack */ - insertPages(insertIndex: number, insertPages: Array<{page: Type, params?: any}>, opts: NavOptions = {}): Promise { + insertPages(insertIndex: number, insertPages: Array<{page: Type, params?: any}>, opts?: NavOptions): Promise { let views = insertPages.map(p => new ViewController(p.page, p.params)); return this._insertViews(insertIndex, views, opts); } - private _insertViews(insertIndex: number, insertViews: Array, opts: NavOptions = {}): Promise { + private _insertViews(insertIndex: number, insertViews: Array, opts?: NavOptions): Promise { if (!insertViews || !insertViews.length) { return Promise.reject('invalid pages'); } + if (isBlank(opts)) { + opts = {}; + } + // insert the new page into the stack // returns the newly created entering view let enteringView = this._insert(insertIndex, insertViews); @@ -616,16 +628,20 @@ export class NavController extends Ion { * @param {object} [opts={}] Any options you want to use pass to transtion * @returns {Promise} Returns a promise when the transition is completed */ - pop(opts: NavOptions = {}): Promise { + pop(opts?: NavOptions): Promise { // get the index of the active view // which will become the view to be leaving let activeView = this.getByState(STATE_TRANS_ENTER) || this.getByState(STATE_INIT_ENTER) || this.getActive(); + if (isBlank(opts)) { + opts = {}; + } + // if not set, by default climb up the nav controllers if // there isn't a previous view in this nav controller - if (isUndefined(opts.climbNav)) { + if (isBlank(opts.climbNav)) { opts.climbNav = true; } return this.remove(this.indexOf(activeView), 1, opts); @@ -635,7 +651,7 @@ export class NavController extends Ion { * Similar to `pop()`, this method let's you navigate back to the root of the stack, no matter how many views that is * @param {object} [opts={}] Any options you want to use pass to transtion */ - popToRoot(opts: NavOptions = {}): Promise { + popToRoot(opts?: NavOptions): Promise { return this.popTo(this.first(), opts); } @@ -644,7 +660,7 @@ export class NavController extends Ion { * @param {ViewController} view to pop to * @param {object} [opts={}] Any options you want to use pass to transtion */ - popTo(view: ViewController, opts: NavOptions = {}): Promise { + popTo(view: ViewController, opts?: NavOptions): Promise { let startIndex = this.indexOf(view); let activeView = this.getByState(STATE_TRANS_ENTER) || this.getByState(STATE_INIT_ENTER) || @@ -673,7 +689,7 @@ export class NavController extends Ion { * @param {object} [opts={}] Any options you want to use pass to transtion. * @returns {Promise} Returns a promise when the page has been removed. */ - remove(startIndex: number = -1, removeCount: number = 1, opts: NavOptions = {}): Promise { + remove(startIndex: number = -1, removeCount: number = 1, opts?: NavOptions): Promise { if (startIndex === -1) { startIndex = this._views.length - 1; @@ -681,6 +697,10 @@ export class NavController extends Ion { return Promise.reject("remove index out of range"); } + if (isBlank(opts)) { + opts = {}; + } + // default the direction to "back" opts.direction = opts.direction || 'back'; @@ -878,8 +898,11 @@ export class NavController extends Ion { // lets time this sucker, ready go let wtfScope = wtfStartTimeRange('NavController#_transition', (enteringView && enteringView.name)); - if (this.config.get('animate') === false || - (this._views.length === 1 && !this._init)) { + if (isBlank(opts)) { + opts = {}; + } + + if (this.config.get('animate') === false || (this._views.length === 1 && !this._init)) { opts.animate = false; } diff --git a/ionic/components/nav/test/basic/index.ts b/ionic/components/nav/test/basic/index.ts index 776e0e2f4d6..99f5a488a26 100644 --- a/ionic/components/nav/test/basic/index.ts +++ b/ionic/components/nav/test/basic/index.ts @@ -45,6 +45,7 @@ class MyCmpTest{} + @@ -62,8 +63,7 @@ class FirstPage { constructor( private nav: NavController, - app: IonicApp, - config: Config + private view: ViewController ) { this.pushPage = FullPage; @@ -110,6 +110,10 @@ class FirstPage { }, 250); } + viewDismiss() { + this.view.dismiss(); + } + reload() { window.location.reload(); } diff --git a/ionic/components/nav/test/nav-controller.spec.ts b/ionic/components/nav/test/nav-controller.spec.ts index 7bffb87a063..7253dbab2ac 100644 --- a/ionic/components/nav/test/nav-controller.spec.ts +++ b/ionic/components/nav/test/nav-controller.spec.ts @@ -74,6 +74,20 @@ export function run() { }); + describe('remove', () => { + + it('should create opts if passed in arg is undefined or null', () => { + let view1 = new ViewController(Page1); + view1.state = STATE_INACTIVE; + let view2 = new ViewController(Page2); + view2.state = STATE_ACTIVE; + nav._views = [view1, view2]; + + nav.remove(1, 1, null); + }); + + }); + describe('_remove', () => { it('should reassign activily transitioning leave that isnt getting removed, to become force active', () => { diff --git a/ionic/components/nav/view-controller.ts b/ionic/components/nav/view-controller.ts index ee61dae2908..062d745b844 100644 --- a/ionic/components/nav/view-controller.ts +++ b/ionic/components/nav/view-controller.ts @@ -3,6 +3,7 @@ import {Output, EventEmitter, Type, TemplateRef, ViewContainerRef, ElementRef, R import {Navbar} from '../navbar/navbar'; import {NavController, NavOptions} from './nav-controller'; import {NavParams} from './nav-params'; +import {isPresent} from '../../util/util'; /** @@ -86,9 +87,9 @@ export class ViewController { */ @Output() private _emitter: EventEmitter = new EventEmitter(); - constructor(public componentType?: Type, data: any = {}) { + constructor(public componentType?: Type, data?: any) { // passed in data could be NavParams, but all we care about is its data object - this.data = (data instanceof NavParams ? data.data : data); + this.data = (data instanceof NavParams ? data.data : isPresent(data) ? data : {}); } subscribe(generatorOrNext?: any): any { diff --git a/ionic/components/option/option.ts b/ionic/components/option/option.ts index 522c254b4cf..b4ddfc269fb 100644 --- a/ionic/components/option/option.ts +++ b/ionic/components/option/option.ts @@ -1,6 +1,6 @@ import {Directive, ElementRef, Input, Output, EventEmitter} from 'angular2/core'; -import {isDefined, isTrueProperty} from '../../util/util'; +import {isPresent, isTrueProperty} from '../../util/util'; /** * @name Option @@ -40,7 +40,7 @@ export class Option { */ @Input() get value() { - if (isDefined(this._value)) { + if (isPresent(this._value)) { return this._value; } return this.text; diff --git a/ionic/components/radio/radio-button.ts b/ionic/components/radio/radio-button.ts index f45a2cd65fd..d5130f1c33a 100644 --- a/ionic/components/radio/radio-button.ts +++ b/ionic/components/radio/radio-button.ts @@ -1,7 +1,7 @@ import {Component, Optional, Input, Output, HostListener, EventEmitter} from 'angular2/core'; import {Form} from '../../util/form'; -import {isTrueProperty, isDefined, isBlank} from '../../util/util'; +import {isTrueProperty, isPresent, isBlank} from '../../util/util'; import {Item} from '../item/item'; import {ListHeader} from '../list/list'; import {RadioGroup} from './radio-group'; @@ -142,7 +142,7 @@ export class RadioButton { * @private */ ngOnInit() { - if (this._group && isDefined(this._group.value) && this._group.value == this.value) { + if (this._group && isPresent(this._group.value) && this._group.value == this.value) { this.checked = true; } } diff --git a/ionic/components/radio/radio-group.ts b/ionic/components/radio/radio-group.ts index fdf64f23f07..6dc45cabb3c 100644 --- a/ionic/components/radio/radio-group.ts +++ b/ionic/components/radio/radio-group.ts @@ -3,7 +3,7 @@ import {NG_VALUE_ACCESSOR} from 'angular2/common'; import {RadioButton} from './radio-button'; import {ListHeader} from '../list/list'; -import {isDefined} from '../../util/util'; +import {isPresent} from '../../util/util'; const RADIO_VALUE_ACCESSOR = new Provider( NG_VALUE_ACCESSOR, {useExisting: forwardRef(() => RadioGroup), multi: true}); diff --git a/ionic/components/searchbar/searchbar.ts b/ionic/components/searchbar/searchbar.ts index f3f95247bae..51e37d49852 100644 --- a/ionic/components/searchbar/searchbar.ts +++ b/ionic/components/searchbar/searchbar.ts @@ -5,7 +5,7 @@ import {Ion} from '../ion'; import {Config} from '../../config/config'; import {Icon} from '../icon/icon'; import {Button} from '../button/button'; -import {isDefined, debounce} from '../../util/util'; +import {isPresent, debounce} from '../../util/util'; /** @@ -206,7 +206,7 @@ export class Searchbar extends Ion { ngAfterViewInit() { // If the user passes an undefined variable to ngModel this will warn // and set the value to an empty string - if (!isDefined(this.value)) { + if (!isPresent(this.value)) { console.warn('Searchbar was passed an undefined value in ngModel. Please make sure the variable is defined.'); this.value = ''; this.onChange(this.value); diff --git a/ionic/components/segment/segment.ts b/ionic/components/segment/segment.ts index e9bb16532ae..6aae3bba2cb 100644 --- a/ionic/components/segment/segment.ts +++ b/ionic/components/segment/segment.ts @@ -1,7 +1,7 @@ import {Directive, Component, ElementRef, Renderer, Optional, EventEmitter, Input, Output, HostListener, ContentChildren, QueryList} from 'angular2/core'; import {NgControl} from 'angular2/common'; -import {isDefined} from '../../util/util'; +import {isPresent} from '../../util/util'; /** @@ -82,7 +82,7 @@ export class SegmentButton { * @private */ ngOnInit() { - if (!isDefined(this.value)) { + if (!isPresent(this.value)) { console.warn(' requires a "value" attribute'); } } @@ -174,7 +174,7 @@ export class Segment { * Write a new value to the element. */ writeValue(value) { - this.value = isDefined(value) ? value : ''; + this.value = isPresent(value) ? value : ''; if (this._buttons) { let buttons = this._buttons.toArray(); for (let button of buttons) { @@ -195,7 +195,7 @@ export class Segment { this.change.emit(selectedButton); }); - if (isDefined(this.value)) { + if (isPresent(this.value)) { button.isActive = (button.value === this.value); } } diff --git a/ionic/components/tabs/tabs.ts b/ionic/components/tabs/tabs.ts index a9996a8afaa..3ebe4acedf0 100644 --- a/ionic/components/tabs/tabs.ts +++ b/ionic/components/tabs/tabs.ts @@ -12,7 +12,7 @@ import {NavController} from '../nav/nav-controller'; import {ViewController} from '../nav/view-controller'; import {Icon} from '../icon/icon'; import {rafFrames} from '../../util/dom'; -import {isUndefined, isTrueProperty} from '../../util/util'; +import {isBlank, isTrueProperty} from '../../util/util'; /** @@ -193,7 +193,7 @@ export class Tabs extends Ion { ngAfterContentInit() { let selectedIndex = this.selectedIndex ? parseInt(this.selectedIndex, 10) : 0; - let preloadTabs = (isUndefined(this.preloadTabs) ? this._config.getBoolean('preloadTabs') : isTrueProperty(this.preloadTabs)); + let preloadTabs = (isBlank(this.preloadTabs) ? this._config.getBoolean('preloadTabs') : isTrueProperty(this.preloadTabs)); this._tabs.forEach((tab, index) => { if (index === selectedIndex) { @@ -210,7 +210,7 @@ export class Tabs extends Ion { */ private _setConfig(attrKey, fallback) { var val = this[attrKey]; - if (isUndefined(val)) { + if (isBlank(val)) { val = this._config.get(attrKey, fallback); } this._renderer.setElementAttribute(this._elementRef.nativeElement, attrKey, val); diff --git a/ionic/util/util.ts b/ionic/util/util.ts index 381608894ff..e66bf5a50c9 100644 --- a/ionic/util/util.ts +++ b/ionic/util/util.ts @@ -106,6 +106,7 @@ export const isNumber = val => typeof val === 'number'; export const isFunction = val => typeof val === 'function'; export const isDefined = val => typeof val !== 'undefined'; export const isUndefined = val => typeof val === 'undefined'; +export const isPresent = val => val !== undefined && val !== null; export const isBlank = val => val === undefined || val === null; export const isObject = val => typeof val === 'object'; export const isArray = Array.isArray;