Skip to content

Commit 4fd05b6

Browse files
authored
fix(nav): getLength is part of the public API (#28832)
resolves #28826 BREAKING CHANGE: `getLength` returns `Promise<number>` instead of `<number>`. This method was not previously available in Nav's TypeScript interface, but developers could still access it by casting Nav as `any`. Developers should ensure they `await` their `getLength` call before accessing the returned value.
1 parent 76f6362 commit 4fd05b6

File tree

5 files changed

+52
-38
lines changed

5 files changed

+52
-38
lines changed

BREAKING.md

+5
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ This is a comprehensive list of the breaking changes introduced in the major ver
1919
- [Button](#version-8x-button)
2020
- [Content](#version-8x-content)
2121
- [Datetime](#version-8x-datetime)
22+
- [Nav](#version-8x-nav)
2223
- [Picker](#version-8x-picker)
2324

2425
<h2 id="version-8x-browser-platform-support">Browser and Platform Support</h2>
@@ -80,6 +81,10 @@ This allows components to inherit the color properly when used outside of Ionic
8081
}
8182
```
8283

84+
<h4 id="version-8x-nav">Nav</h4>
85+
86+
- `getLength` returns `Promise<number>` instead of `<number>`. This method was not previously available in Nav's TypeScript interface, but developers could still access it by casting Nav as `any`. Developers should ensure they `await` their `getLength` call before accessing the returned value.
87+
8388
<h4 id="version-8x-picker">Picker</h4>
8489

8590
- `ion-picker` and `ion-picker-column` have been renamed to `ion-picker-legacy` and `ion-picker-legacy-column`, respectively. This change was made to accommodate the new inline picker component while allowing developers to continue to use the legacy picker during this migration period.

core/api.txt

+1
Original file line numberDiff line numberDiff line change
@@ -884,6 +884,7 @@ ion-nav,prop,swipeGesture,boolean | undefined,undefined,false,false
884884
ion-nav,method,canGoBack,canGoBack(view?: ViewController) => Promise<boolean>
885885
ion-nav,method,getActive,getActive() => Promise<ViewController | undefined>
886886
ion-nav,method,getByIndex,getByIndex(index: number) => Promise<ViewController | undefined>
887+
ion-nav,method,getLength,getLength() => Promise<number>
887888
ion-nav,method,getPrevious,getPrevious(view?: ViewController) => Promise<ViewController | undefined>
888889
ion-nav,method,insert,insert<T extends NavComponent>(insertIndex: number, component: T, componentProps?: ComponentProps<T> | null, opts?: NavOptions | null, done?: TransitionDoneFn) => Promise<boolean>
889890
ion-nav,method,insertPages,insertPages(insertIndex: number, insertComponents: NavComponent[] | NavComponentWithProps[], opts?: NavOptions | null, done?: TransitionDoneFn) => Promise<boolean>

core/src/components.d.ts

+4
Original file line numberDiff line numberDiff line change
@@ -1822,6 +1822,10 @@ export namespace Components {
18221822
* @param index The index of the view.
18231823
*/
18241824
"getByIndex": (index: number) => Promise<ViewController | undefined>;
1825+
/**
1826+
* Returns the number of views in the stack.
1827+
*/
1828+
"getLength": () => Promise<number>;
18251829
/**
18261830
* Get the previous view.
18271831
* @param view The view to get.

core/src/components/nav/nav.tsx

+6-2
Original file line numberDiff line numberDiff line change
@@ -483,8 +483,12 @@ export class Nav implements NavOutlet {
483483
return this.getPreviousSync(view);
484484
}
485485

486-
getLength() {
487-
return this.views.length;
486+
/**
487+
* Returns the number of views in the stack.
488+
*/
489+
@Method()
490+
async getLength(): Promise<number> {
491+
return Promise.resolve(this.views.length);
488492
}
489493

490494
private getActiveSync(): ViewController | undefined {

core/src/components/nav/test/nav-controller.spec.ts

+36-36
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ describe('NavController', () => {
2323
const hasCompleted = true;
2424
const requiresTransition = true;
2525
expect(push1Done).toHaveBeenCalledWith(hasCompleted, requiresTransition, view1, undefined, 'forward');
26-
expect(nav.getLength()).toEqual(1);
26+
expect(await nav.getLength()).toEqual(1);
2727
expect(nav['views'][0].component).toEqual(MockView1);
2828

2929
// Push 2
@@ -32,7 +32,7 @@ describe('NavController', () => {
3232

3333
expect(push2Done).toHaveBeenCalledWith(hasCompleted, requiresTransition, view2, view1, 'forward');
3434

35-
expect(nav.getLength()).toEqual(2);
35+
expect(await nav.getLength()).toEqual(2);
3636
expect(nav['views'][0].component).toEqual(MockView1);
3737
expect(nav['views'][1].component).toEqual(MockView2);
3838

@@ -41,7 +41,7 @@ describe('NavController', () => {
4141
await nav.push(view3, null, { animated: false }, push3Done);
4242

4343
expect(push3Done).toHaveBeenCalledWith(hasCompleted, requiresTransition, view3, view2, 'forward');
44-
expect(nav.getLength()).toEqual(3);
44+
expect(await nav.getLength()).toEqual(3);
4545
expect(nav['views'][0].component).toEqual(MockView1);
4646
expect(nav['views'][1].component).toEqual(MockView2);
4747
expect(nav['views'][2].component).toEqual(MockView3);
@@ -50,7 +50,7 @@ describe('NavController', () => {
5050
const view4 = mockView(MockView4);
5151
await nav.push(view4, null, { animated: false }, push4Done);
5252
expect(push4Done).toHaveBeenCalledWith(hasCompleted, requiresTransition, view4, view3, 'forward');
53-
expect(nav.getLength()).toEqual(4);
53+
expect(await nav.getLength()).toEqual(4);
5454
expect(nav['views'][0].component).toEqual(MockView1);
5555
expect(nav['views'][1].component).toEqual(MockView2);
5656
expect(nav['views'][2].component).toEqual(MockView3);
@@ -59,22 +59,22 @@ describe('NavController', () => {
5959
// Pop 1
6060
await nav.pop({ animated: false }, pop1Done);
6161
expect(pop1Done).toHaveBeenCalledWith(hasCompleted, requiresTransition, view3, view4, 'back');
62-
expect(nav.getLength()).toEqual(3);
62+
expect(await nav.getLength()).toEqual(3);
6363
expect(nav['views'][0].component).toEqual(MockView1);
6464
expect(nav['views'][1].component).toEqual(MockView2);
6565
expect(nav['views'][2].component).toEqual(MockView3);
6666

6767
// Pop 2
6868
await nav.pop({ animated: false }, pop2Done);
6969
expect(pop2Done).toHaveBeenCalledWith(hasCompleted, requiresTransition, view2, view3, 'back');
70-
expect(nav.getLength()).toEqual(2);
70+
expect(await nav.getLength()).toEqual(2);
7171
expect(nav['views'][0].component).toEqual(MockView1);
7272
expect(nav['views'][1].component).toEqual(MockView2);
7373

7474
// Pop 3
7575
await nav.pop({ animated: false }, pop3Done);
7676
expect(pop3Done).toHaveBeenCalledWith(hasCompleted, requiresTransition, view1, view2, 'back');
77-
expect(nav.getLength()).toEqual(1);
77+
expect(await nav.getLength()).toEqual(1);
7878
expect(nav['views'][0].component).toEqual(MockView1);
7979
}, 10000);
8080
});
@@ -86,7 +86,7 @@ describe('NavController', () => {
8686
const hasCompleted = true;
8787
const requiresTransition = true;
8888
expect(trnsDone).toHaveBeenCalledWith(hasCompleted, requiresTransition, view1, undefined, 'forward');
89-
expect(nav.getLength()).toEqual(1);
89+
expect(await nav.getLength()).toEqual(1);
9090
expect(nav['views'][0].component).toEqual(MockView1);
9191
expect(nav['isTransitioning']).toEqual(false);
9292
}, 10000);
@@ -102,7 +102,7 @@ describe('NavController', () => {
102102
const hasCompleted = true;
103103
const requiresTransition = true;
104104
expect(trnsDone).toHaveBeenCalledWith(hasCompleted, requiresTransition, view2, view1, 'forward');
105-
expect(nav.getLength()).toEqual(2);
105+
expect(await nav.getLength()).toEqual(2);
106106
expect(nav['views'][0].component).toEqual(MockView1);
107107
expect(nav['views'][1].component).toEqual(MockView2);
108108
expect(nav['isTransitioning']).toEqual(false);
@@ -134,7 +134,7 @@ describe('NavController', () => {
134134
const hasCompleted = true;
135135
const requiresTransition = true;
136136
expect(trnsDone).toHaveBeenCalledWith(hasCompleted, requiresTransition, view2, view1, 'forward');
137-
expect(nav.getLength()).toEqual(2);
137+
expect(await nav.getLength()).toEqual(2);
138138
}, 10000);
139139
});
140140

@@ -156,9 +156,9 @@ describe('NavController', () => {
156156
const hasCompleted = true;
157157
const requiresTransition = false;
158158
expect(trnsDone).toHaveBeenCalledWith(hasCompleted, requiresTransition, undefined, undefined, undefined);
159-
expect(nav.getLength()).toEqual(4);
159+
expect(await nav.getLength()).toEqual(4);
160160
expect(nav['views'][0].component).toEqual(MockView4);
161-
expect(nav['views'][nav.getLength() - 1].component).toEqual(MockView3);
161+
expect(nav['views'][(await nav.getLength()) - 1].component).toEqual(MockView3);
162162
}, 10000);
163163

164164
it('should insert at the end when given -1', async () => {
@@ -172,8 +172,8 @@ describe('NavController', () => {
172172
const hasCompleted = true;
173173
const requiresTransition = true;
174174
expect(trnsDone).toHaveBeenCalledWith(hasCompleted, requiresTransition, view2, view1, 'forward');
175-
expect(nav.getLength()).toEqual(2);
176-
expect(nav['views'][nav.getLength() - 1].component).toEqual(MockView2);
175+
expect(await nav.getLength()).toEqual(2);
176+
expect(nav['views'][(await nav.getLength()) - 1].component).toEqual(MockView2);
177177
}, 10000);
178178

179179
it('should insert at the end when given a number greater than actual length', async () => {
@@ -185,8 +185,8 @@ describe('NavController', () => {
185185
const hasCompleted = true;
186186
const requiresTransition = true;
187187
expect(trnsDone).toHaveBeenCalledWith(hasCompleted, requiresTransition, view2, view1, 'forward');
188-
expect(nav.getLength()).toEqual(2);
189-
expect(nav['views'][nav.getLength() - 1].component).toEqual(MockView2);
188+
expect(await nav.getLength()).toEqual(2);
189+
expect(nav['views'][(await nav.getLength()) - 1].component).toEqual(MockView2);
190190
}, 10000);
191191

192192
it('should not insert if null view', (done) => {
@@ -197,14 +197,14 @@ describe('NavController', () => {
197197
.then(() => {
198198
fail('it should not succeed');
199199
})
200-
.catch((err: Error) => {
200+
.catch(async (err: Error) => {
201201
const hasCompleted = false;
202202
const requiresTransition = false;
203203
const rejectReason = new Error('invalid views to insert');
204204
expect(err).toEqual(rejectReason);
205205
expect(trnsDone).toHaveBeenCalledWith(hasCompleted, requiresTransition, rejectReason);
206-
expect(nav.getLength()).toEqual(1);
207-
expect(nav['views'][nav.getLength() - 1].component).toEqual(MockView1);
206+
expect(await nav.getLength()).toEqual(1);
207+
expect(nav['views'][(await nav.getLength()) - 1].component).toEqual(MockView1);
208208
done();
209209
});
210210
}, 10000);
@@ -232,7 +232,7 @@ describe('NavController', () => {
232232
const hasCompleted = true;
233233
const requiresTransition = false;
234234
expect(trnsDone).toHaveBeenCalledWith(hasCompleted, requiresTransition, undefined, undefined, undefined);
235-
expect(nav.getLength()).toEqual(5);
235+
expect(await nav.getLength()).toEqual(5);
236236
expect(nav['views'][0].component).toEqual(MockView1);
237237
expect(nav['views'][1].component).toEqual(MockView4);
238238
expect(nav['views'][2].component).toEqual(MockView5);
@@ -251,13 +251,13 @@ describe('NavController', () => {
251251
.then(() => {
252252
fail('it should not succeed');
253253
})
254-
.catch((err: any) => {
254+
.catch(async (err: any) => {
255255
const hasCompleted = false;
256256
const requiresTransition = false;
257257
const rejectReason = new Error('no views in the stack to be removed');
258258
expect(trnsDone).toHaveBeenCalledWith(hasCompleted, requiresTransition, rejectReason);
259259
expect(err).toEqual(rejectReason);
260-
expect(nav.getLength()).toEqual(0);
260+
expect(await nav.getLength()).toEqual(0);
261261
expect(nav['isTransitioning']).toEqual(false);
262262
done();
263263
});
@@ -287,7 +287,7 @@ describe('NavController', () => {
287287
const hasCompleted = true;
288288
const requiresTransition = true;
289289
expect(trnsDone).toHaveBeenCalledWith(hasCompleted, requiresTransition, view1, view2, 'back');
290-
expect(nav.getLength()).toEqual(1);
290+
expect(await nav.getLength()).toEqual(1);
291291
expect(nav['views'][0].component).toEqual(MockView1);
292292
expect(nav['isTransitioning']).toEqual(false);
293293
}, 10000);
@@ -305,7 +305,7 @@ describe('NavController', () => {
305305
const hasCompleted = true;
306306
const requiresTransition = true;
307307
expect(trnsDone).toHaveBeenCalledWith(hasCompleted, requiresTransition, view2, view3, 'back');
308-
expect(nav.getLength()).toEqual(2);
308+
expect(await nav.getLength()).toEqual(2);
309309
expect(nav['views'][0].component).toEqual(MockView1);
310310
expect(nav['views'][1].component).toEqual(MockView2);
311311
}, 10000);
@@ -322,7 +322,7 @@ describe('NavController', () => {
322322
const hasCompleted = true;
323323
const requiresTransition = true;
324324
expect(trnsDone).toHaveBeenCalledWith(hasCompleted, requiresTransition, view2, view4, 'back');
325-
expect(nav.getLength()).toEqual(2);
325+
expect(await nav.getLength()).toEqual(2);
326326
expect(nav['views'][0].component).toEqual(MockView1);
327327
expect(nav['views'][1].component).toEqual(MockView2);
328328
}, 10000);
@@ -368,7 +368,7 @@ describe('NavController', () => {
368368
const hasCompleted = true;
369369
const requiresTransition = true;
370370
expect(trnsDone).toHaveBeenCalledWith(hasCompleted, requiresTransition, view1, view4, 'back');
371-
expect(nav.getLength()).toEqual(1);
371+
expect(await nav.getLength()).toEqual(1);
372372
expect(nav['views'][0].component).toEqual(MockView1);
373373
}, 10000);
374374
});
@@ -415,7 +415,7 @@ describe('NavController', () => {
415415
const hasCompleted = true;
416416
const requiresTransition = true;
417417
expect(trnsDone).toHaveBeenCalledWith(hasCompleted, requiresTransition, view1, view4, 'back');
418-
expect(nav.getLength()).toEqual(1);
418+
expect(await nav.getLength()).toEqual(1);
419419
expect(nav['views'][0].component).toEqual(MockView1);
420420
}, 10000);
421421

@@ -427,7 +427,7 @@ describe('NavController', () => {
427427
const hasCompleted = true;
428428
const requiresTransition = false;
429429
expect(trnsDone).toHaveBeenCalledWith(hasCompleted, requiresTransition, undefined, undefined, undefined);
430-
expect(nav.getLength()).toEqual(1);
430+
expect(await nav.getLength()).toEqual(1);
431431
expect(nav['views'][0].component).toEqual(MockView1);
432432
}, 10000);
433433
});
@@ -474,7 +474,7 @@ describe('NavController', () => {
474474
const hasCompleted = true;
475475
const requiresTransition = false;
476476
expect(trnsDone).toHaveBeenCalledWith(hasCompleted, requiresTransition, undefined, undefined, undefined);
477-
expect(nav.getLength()).toEqual(1);
477+
expect(await nav.getLength()).toEqual(1);
478478
expect(nav['views'][0].component).toEqual(MockView4);
479479
}, 10000);
480480

@@ -527,7 +527,7 @@ describe('NavController', () => {
527527
const hasCompleted = true;
528528
const requiresTransition = false;
529529
expect(trnsDone).toHaveBeenCalledWith(hasCompleted, requiresTransition, undefined, undefined, undefined);
530-
expect(nav.getLength()).toEqual(3);
530+
expect(await nav.getLength()).toEqual(3);
531531
expect(nav['views'][0].component).toEqual(MockView1);
532532
expect(nav['views'][1].component).toEqual(MockView2);
533533
expect(nav['views'][2].component).toEqual(MockView5);
@@ -574,7 +574,7 @@ describe('NavController', () => {
574574
const hasCompleted = true;
575575
const requiresTransition = true;
576576
expect(trnsDone).toHaveBeenCalledWith(hasCompleted, requiresTransition, view2, view4, 'back');
577-
expect(nav.getLength()).toEqual(2);
577+
expect(await nav.getLength()).toEqual(2);
578578
expect(nav['views'][0].component).toEqual(MockView1);
579579
expect(nav['views'][1].component).toEqual(MockView2);
580580
}, 10000);
@@ -613,7 +613,7 @@ describe('NavController', () => {
613613
const hasCompleted = true;
614614
const requiresTransition = false;
615615
expect(trnsDone).toHaveBeenCalledWith(hasCompleted, requiresTransition, undefined, undefined, undefined);
616-
expect(nav.getLength()).toEqual(1);
616+
expect(await nav.getLength()).toEqual(1);
617617
expect(nav['views'][0].component).toEqual(MockView3);
618618
}, 10000);
619619

@@ -649,7 +649,7 @@ describe('NavController', () => {
649649
const hasCompleted = true;
650650
const requiresTransition = true;
651651
expect(trnsDone).toHaveBeenCalledWith(hasCompleted, requiresTransition, view2, view3, 'back');
652-
expect(nav.getLength()).toEqual(1);
652+
expect(await nav.getLength()).toEqual(1);
653653
expect(nav['views'][0].component).toEqual(MockView2);
654654
}, 10000);
655655

@@ -685,7 +685,7 @@ describe('NavController', () => {
685685
const hasCompleted = true;
686686
const requiresTransition = true;
687687
expect(trnsDone).toHaveBeenCalledWith(hasCompleted, requiresTransition, view1, view3, 'back');
688-
expect(nav.getLength()).toEqual(1);
688+
expect(await nav.getLength()).toEqual(1);
689689
expect(nav['views'][0].component).toEqual(MockView1);
690690
}, 10000);
691691

@@ -708,7 +708,7 @@ describe('NavController', () => {
708708
const hasCompleted = true;
709709
const requiresTransition = true;
710710
expect(trnsDone).toHaveBeenCalledWith(hasCompleted, requiresTransition, view4, view3, 'back');
711-
expect(nav.getLength()).toEqual(1);
711+
expect(await nav.getLength()).toEqual(1);
712712
expect(nav['views'][0].component).toEqual(MockView4);
713713
}, 10000);
714714
});
@@ -732,7 +732,7 @@ describe('NavController', () => {
732732
const hasCompleted = true;
733733
const requiresTransition = true;
734734
expect(trnsDone).toHaveBeenCalledWith(hasCompleted, requiresTransition, view5, view2, 'back');
735-
expect(nav.getLength()).toEqual(2);
735+
expect(await nav.getLength()).toEqual(2);
736736
expect(nav['views'][0].component).toEqual(MockView4);
737737
expect(nav['views'][1].component).toEqual(MockView5);
738738
}, 10000);

0 commit comments

Comments
 (0)