Skip to content

Commit 8975016

Browse files
committed
fix(nav): create opts object when undefined/null
Closes #5737
1 parent 5863e2c commit 8975016

File tree

14 files changed

+84
-42
lines changed

14 files changed

+84
-42
lines changed

ionic/components/action-sheet/action-sheet.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {Animation} from '../../animations/animation';
55
import {Transition, TransitionOptions} from '../../transitions/transition';
66
import {Config} from '../../config/config';
77
import {Icon} from '../icon/icon';
8-
import {isDefined} from '../../util/util';
8+
import {isPresent} from '../../util/util';
99
import {NavParams} from '../nav/nav-params';
1010
import {ViewController} from '../nav/view-controller';
1111

@@ -82,7 +82,7 @@ export class ActionSheet extends ViewController {
8282

8383
constructor(opts: ActionSheetOptions = {}) {
8484
opts.buttons = opts.buttons || [];
85-
opts.enableBackdropDismiss = isDefined(opts.enableBackdropDismiss) ? !!opts.enableBackdropDismiss : true;
85+
opts.enableBackdropDismiss = isPresent(opts.enableBackdropDismiss) ? !!opts.enableBackdropDismiss : true;
8686

8787
super(ActionSheetCmp, opts);
8888
this.viewType = 'action-sheet';

ionic/components/alert/alert.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import {NgClass, NgSwitch, NgIf, NgFor} from 'angular2/common';
44
import {Animation} from '../../animations/animation';
55
import {Transition, TransitionOptions} from '../../transitions/transition';
66
import {Config} from '../../config/config';
7-
import {isDefined} from '../../util/util';
7+
import {isPresent} from '../../util/util';
88
import {NavParams} from '../nav/nav-params';
99
import {ViewController} from '../nav/view-controller';
1010

@@ -122,7 +122,7 @@ export class Alert extends ViewController {
122122
constructor(opts: AlertOptions = {}) {
123123
opts.inputs = opts.inputs || [];
124124
opts.buttons = opts.buttons || [];
125-
opts.enableBackdropDismiss = isDefined(opts.enableBackdropDismiss) ? !!opts.enableBackdropDismiss : true;
125+
opts.enableBackdropDismiss = isPresent(opts.enableBackdropDismiss) ? !!opts.enableBackdropDismiss : true;
126126

127127
super(AlertCmp, opts);
128128
this.viewType = 'alert';
@@ -326,9 +326,9 @@ class AlertCmp {
326326
data.inputs = data.inputs.map((input, index) => {
327327
return {
328328
type: input.type || 'text',
329-
name: isDefined(input.name) ? input.name : index,
330-
placeholder: isDefined(input.placeholder) ? input.placeholder : '',
331-
value: isDefined(input.value) ? input.value : '',
329+
name: isPresent(input.name) ? input.name : index,
330+
placeholder: isPresent(input.placeholder) ? input.placeholder : '',
331+
value: isPresent(input.value) ? input.value : '',
332332
label: input.label,
333333
checked: !!input.checked,
334334
id: 'alert-input-' + this.id + '-' + index

ionic/components/list/list.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import {Directive, ElementRef, Renderer, Attribute, NgZone} from 'angular2/core'
22

33
import {Ion} from '../ion';
44
import {ItemSlidingGesture} from '../item/item-sliding-gesture';
5-
import {isDefined} from '../../util';
65

76
/**
87
* The List is a widely used interface element in almost any mobile app,

ionic/components/nav/nav-controller.ts

Lines changed: 39 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {IonicApp} from '../app/app';
77
import {Keyboard} from '../../util/keyboard';
88
import {NavParams} from './nav-params';
99
import {NavRouter} from './nav-router';
10-
import {pascalCaseToDashCase, isTrueProperty, isUndefined} from '../../util/util';
10+
import {pascalCaseToDashCase, isTrueProperty, isBlank} from '../../util/util';
1111
import {raf} from '../../util/dom';
1212
import {SwipeBackGesture} from './swipe-back';
1313
import {Transition} from '../../transitions/transition';
@@ -178,7 +178,7 @@ export class NavController extends Ion {
178178
* @param {object} [opts={}] Any options you want to use pass to transtion
179179
* @returns {Promise} Returns a promise when done
180180
*/
181-
setRoot(page: Type, params: any = {}, opts: NavOptions = {}): Promise<any> {
181+
setRoot(page: Type, params?: any, opts?: NavOptions): Promise<any> {
182182
return this.setPages([{page, params}], opts);
183183
}
184184

@@ -255,11 +255,15 @@ export class NavController extends Ion {
255255
* @param {object} [opts={}] Any options you want to use pass
256256
* @returns {Promise} Returns a promise when the pages are set
257257
*/
258-
setPages(pages: Array<{page: Type, params?: any}>, opts: NavOptions = {}): Promise<any> {
258+
setPages(pages: Array<{page: Type, params?: any}>, opts?: NavOptions): Promise<any> {
259259
if (!pages || !pages.length) {
260260
return Promise.resolve(false);
261261
}
262262

263+
if (isBlank(opts)) {
264+
opts = {};
265+
}
266+
263267
// deprecated warning
264268
pages.forEach(pg => {
265269
if (pg['componentType']) {
@@ -303,7 +307,7 @@ export class NavController extends Ion {
303307
/**
304308
* @private
305309
*/
306-
private setViews(components, opts: NavOptions = {}) {
310+
private setViews(components, opts?: NavOptions) {
307311
console.warn('setViews() deprecated, use setPages() instead');
308312
return this.setPages(components, opts);
309313
}
@@ -373,7 +377,7 @@ export class NavController extends Ion {
373377
* @param {object} [opts={}] Any options you want to use pass to transtion
374378
* @returns {Promise} Returns a promise, which resolves when the transition has completed
375379
*/
376-
push(page: Type, params: any = {}, opts: NavOptions = {}) {
380+
push(page: Type, params?: any, opts?: NavOptions) {
377381
return this.insertPages(-1, [{page: page, params: params}], opts);
378382
}
379383

@@ -402,7 +406,7 @@ export class NavController extends Ion {
402406
* @param {object} [opts={}] Any options you want to use pass to transtion
403407
* @returns {Promise} Returns a promise, which resolves when the transition has completed
404408
*/
405-
present(enteringView: ViewController, opts: NavOptions = {}): Promise<any> {
409+
present(enteringView: ViewController, opts?: NavOptions): Promise<any> {
406410
let rootNav = this.rootNav;
407411

408412
if (rootNav['_tabs']) {
@@ -412,6 +416,10 @@ export class NavController extends Ion {
412416
return;
413417
}
414418

419+
if (isBlank(opts)) {
420+
opts = {};
421+
}
422+
415423
enteringView.setNav(rootNav);
416424

417425
opts.keyboardClose = false;
@@ -454,7 +462,7 @@ export class NavController extends Ion {
454462
* @param {object} [opts={}] Any options you want to use pass to transtion
455463
* @returns {Promise} Returns a promise when the page has been inserted into the navigation stack
456464
*/
457-
insert(insertIndex: number, page: Type, params: any = {}, opts: NavOptions = {}): Promise<any> {
465+
insert(insertIndex: number, page: Type, params?: any, opts?: NavOptions): Promise<any> {
458466
return this.insertPages(insertIndex, [{page: page, params: params}], opts);
459467
}
460468

@@ -486,16 +494,20 @@ export class NavController extends Ion {
486494
* @param {object} [opts={}] Any options you want to use pass to transtion
487495
* @returns {Promise} Returns a promise when the pages have been inserted into the navigation stack
488496
*/
489-
insertPages(insertIndex: number, insertPages: Array<{page: Type, params?: any}>, opts: NavOptions = {}): Promise<any> {
497+
insertPages(insertIndex: number, insertPages: Array<{page: Type, params?: any}>, opts?: NavOptions): Promise<any> {
490498
let views = insertPages.map(p => new ViewController(p.page, p.params));
491499
return this._insertViews(insertIndex, views, opts);
492500
}
493501

494-
private _insertViews(insertIndex: number, insertViews: Array<ViewController>, opts: NavOptions = {}): Promise<any> {
502+
private _insertViews(insertIndex: number, insertViews: Array<ViewController>, opts?: NavOptions): Promise<any> {
495503
if (!insertViews || !insertViews.length) {
496504
return Promise.reject('invalid pages');
497505
}
498506

507+
if (isBlank(opts)) {
508+
opts = {};
509+
}
510+
499511
// insert the new page into the stack
500512
// returns the newly created entering view
501513
let enteringView = this._insert(insertIndex, insertViews);
@@ -616,16 +628,20 @@ export class NavController extends Ion {
616628
* @param {object} [opts={}] Any options you want to use pass to transtion
617629
* @returns {Promise} Returns a promise when the transition is completed
618630
*/
619-
pop(opts: NavOptions = {}): Promise<any> {
631+
pop(opts?: NavOptions): Promise<any> {
620632
// get the index of the active view
621633
// which will become the view to be leaving
622634
let activeView = this.getByState(STATE_TRANS_ENTER) ||
623635
this.getByState(STATE_INIT_ENTER) ||
624636
this.getActive();
625637

638+
if (isBlank(opts)) {
639+
opts = {};
640+
}
641+
626642
// if not set, by default climb up the nav controllers if
627643
// there isn't a previous view in this nav controller
628-
if (isUndefined(opts.climbNav)) {
644+
if (isBlank(opts.climbNav)) {
629645
opts.climbNav = true;
630646
}
631647
return this.remove(this.indexOf(activeView), 1, opts);
@@ -635,7 +651,7 @@ export class NavController extends Ion {
635651
* Similar to `pop()`, this method let's you navigate back to the root of the stack, no matter how many views that is
636652
* @param {object} [opts={}] Any options you want to use pass to transtion
637653
*/
638-
popToRoot(opts: NavOptions = {}): Promise<any> {
654+
popToRoot(opts?: NavOptions): Promise<any> {
639655
return this.popTo(this.first(), opts);
640656
}
641657

@@ -644,7 +660,7 @@ export class NavController extends Ion {
644660
* @param {ViewController} view to pop to
645661
* @param {object} [opts={}] Any options you want to use pass to transtion
646662
*/
647-
popTo(view: ViewController, opts: NavOptions = {}): Promise<any> {
663+
popTo(view: ViewController, opts?: NavOptions): Promise<any> {
648664
let startIndex = this.indexOf(view);
649665
let activeView = this.getByState(STATE_TRANS_ENTER) ||
650666
this.getByState(STATE_INIT_ENTER) ||
@@ -673,14 +689,18 @@ export class NavController extends Ion {
673689
* @param {object} [opts={}] Any options you want to use pass to transtion.
674690
* @returns {Promise} Returns a promise when the page has been removed.
675691
*/
676-
remove(startIndex: number = -1, removeCount: number = 1, opts: NavOptions = {}): Promise<any> {
692+
remove(startIndex: number = -1, removeCount: number = 1, opts?: NavOptions): Promise<any> {
677693
if (startIndex === -1) {
678694
startIndex = this._views.length - 1;
679695

680696
} else if (startIndex < 0 || startIndex >= this._views.length) {
681697
return Promise.reject("remove index out of range");
682698
}
683699

700+
if (isBlank(opts)) {
701+
opts = {};
702+
}
703+
684704
// default the direction to "back"
685705
opts.direction = opts.direction || 'back';
686706

@@ -878,8 +898,11 @@ export class NavController extends Ion {
878898
// lets time this sucker, ready go
879899
let wtfScope = wtfStartTimeRange('NavController#_transition', (enteringView && enteringView.name));
880900

881-
if (this.config.get('animate') === false ||
882-
(this._views.length === 1 && !this._init)) {
901+
if (isBlank(opts)) {
902+
opts = {};
903+
}
904+
905+
if (this.config.get('animate') === false || (this._views.length === 1 && !this._init)) {
883906
opts.animate = false;
884907
}
885908

ionic/components/nav/test/basic/index.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ class MyCmpTest{}
4545
<button ion-item (click)="setPages()">setPages() (Go to PrimaryHeaderPage)</button>
4646
<button ion-item (click)="setRoot()">setRoot(PrimaryHeaderPage) (Go to PrimaryHeaderPage)</button>
4747
<button ion-item (click)="nav.pop()">Pop</button>
48+
<button ion-item (click)="viewDismiss()">View Dismiss</button>
4849
<button ion-item (click)="quickPush()">New push during transition</button>
4950
<button ion-item (click)="quickPop()">New pop during transition</button>
5051
<button ion-item (click)="reload()">Reload</button>
@@ -62,8 +63,7 @@ class FirstPage {
6263

6364
constructor(
6465
private nav: NavController,
65-
app: IonicApp,
66-
config: Config
66+
private view: ViewController
6767
) {
6868
this.pushPage = FullPage;
6969

@@ -110,6 +110,10 @@ class FirstPage {
110110
}, 250);
111111
}
112112

113+
viewDismiss() {
114+
this.view.dismiss();
115+
}
116+
113117
reload() {
114118
window.location.reload();
115119
}

ionic/components/nav/test/nav-controller.spec.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,20 @@ export function run() {
7474

7575
});
7676

77+
describe('remove', () => {
78+
79+
it('should create opts if passed in arg is undefined or null', () => {
80+
let view1 = new ViewController(Page1);
81+
view1.state = STATE_INACTIVE;
82+
let view2 = new ViewController(Page2);
83+
view2.state = STATE_ACTIVE;
84+
nav._views = [view1, view2];
85+
86+
nav.remove(1, 1, null);
87+
});
88+
89+
});
90+
7791
describe('_remove', () => {
7892

7993
it('should reassign activily transitioning leave that isnt getting removed, to become force active', () => {

ionic/components/nav/view-controller.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {Output, EventEmitter, Type, TemplateRef, ViewContainerRef, ElementRef, R
33
import {Navbar} from '../navbar/navbar';
44
import {NavController, NavOptions} from './nav-controller';
55
import {NavParams} from './nav-params';
6+
import {isPresent} from '../../util/util';
67

78

89
/**
@@ -86,9 +87,9 @@ export class ViewController {
8687
*/
8788
@Output() private _emitter: EventEmitter<any> = new EventEmitter();
8889

89-
constructor(public componentType?: Type, data: any = {}) {
90+
constructor(public componentType?: Type, data?: any) {
9091
// passed in data could be NavParams, but all we care about is its data object
91-
this.data = (data instanceof NavParams ? data.data : data);
92+
this.data = (data instanceof NavParams ? data.data : isPresent(data) ? data : {});
9293
}
9394

9495
subscribe(generatorOrNext?: any): any {

ionic/components/option/option.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {Directive, ElementRef, Input, Output, EventEmitter} from 'angular2/core';
22

3-
import {isDefined, isTrueProperty} from '../../util/util';
3+
import {isPresent, isTrueProperty} from '../../util/util';
44

55
/**
66
* @name Option
@@ -40,7 +40,7 @@ export class Option {
4040
*/
4141
@Input()
4242
get value() {
43-
if (isDefined(this._value)) {
43+
if (isPresent(this._value)) {
4444
return this._value;
4545
}
4646
return this.text;

ionic/components/radio/radio-button.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import {Component, Optional, Input, Output, HostListener, EventEmitter} from 'angular2/core';
22

33
import {Form} from '../../util/form';
4-
import {isTrueProperty, isDefined, isBlank} from '../../util/util';
4+
import {isTrueProperty, isPresent, isBlank} from '../../util/util';
55
import {Item} from '../item/item';
66
import {ListHeader} from '../list/list';
77
import {RadioGroup} from './radio-group';
@@ -142,7 +142,7 @@ export class RadioButton {
142142
* @private
143143
*/
144144
ngOnInit() {
145-
if (this._group && isDefined(this._group.value) && this._group.value == this.value) {
145+
if (this._group && isPresent(this._group.value) && this._group.value == this.value) {
146146
this.checked = true;
147147
}
148148
}

ionic/components/radio/radio-group.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import {NG_VALUE_ACCESSOR} from 'angular2/common';
33

44
import {RadioButton} from './radio-button';
55
import {ListHeader} from '../list/list';
6-
import {isDefined} from '../../util/util';
6+
import {isPresent} from '../../util/util';
77

88
const RADIO_VALUE_ACCESSOR = new Provider(
99
NG_VALUE_ACCESSOR, {useExisting: forwardRef(() => RadioGroup), multi: true});

ionic/components/searchbar/searchbar.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {Ion} from '../ion';
55
import {Config} from '../../config/config';
66
import {Icon} from '../icon/icon';
77
import {Button} from '../button/button';
8-
import {isDefined, debounce} from '../../util/util';
8+
import {isPresent, debounce} from '../../util/util';
99

1010

1111
/**
@@ -206,7 +206,7 @@ export class Searchbar extends Ion {
206206
ngAfterViewInit() {
207207
// If the user passes an undefined variable to ngModel this will warn
208208
// and set the value to an empty string
209-
if (!isDefined(this.value)) {
209+
if (!isPresent(this.value)) {
210210
console.warn('Searchbar was passed an undefined value in ngModel. Please make sure the variable is defined.');
211211
this.value = '';
212212
this.onChange(this.value);

0 commit comments

Comments
 (0)