diff --git a/apps/tests/ui/tab-view/tab-view-tests.ts b/apps/tests/ui/tab-view/tab-view-tests.ts index e4b089448..e6d240587 100644 --- a/apps/tests/ui/tab-view/tab-view-tests.ts +++ b/apps/tests/ui/tab-view/tab-view-tests.ts @@ -308,6 +308,83 @@ export var testWhenSelectingATabNativelySelectedIndexIsUpdatedProperly = functio } } +export var testWhenSelectingATabNativelySelectedIndexChangedEventIsRaised = function () { + var tabView: tabViewModule.TabView; + var mainPage: pageModule.Page; + var pageFactory = function (): pageModule.Page { + tabView = _createTabView(); + tabView.items = _createItems(10); + mainPage = new pageModule.Page(); + mainPage.content = tabView; + return mainPage; + }; + + helper.navigate(pageFactory); + + var expectedOldIndex = 3; + var expectedNewIndex = 5; + var actualOldIndex; + var actualNewIndex; + + tabViewTestsNative.selectNativeTab(tabView, expectedOldIndex); + TKUnit.wait(helper.ASYNC); + + tabView.on(tabViewModule.TabView.selectedIndexChangedEvent,(args: tabViewModule.SelectedIndexChangedEventData) => { + actualOldIndex = args.oldIndex; + actualNewIndex = args.newIndex; + }); + + tabViewTestsNative.selectNativeTab(tabView, expectedNewIndex); + TKUnit.wait(helper.ASYNC); + + try { + TKUnit.assert(actualOldIndex === expectedOldIndex, "Actual: " + actualOldIndex + "; Expected: " + expectedOldIndex); + TKUnit.assert(actualNewIndex === expectedNewIndex, "Actual: " + actualNewIndex + "; Expected: " + expectedNewIndex); + } + finally { + helper.goBack(); + } +} + +export var testWhenSettingSelectedIndexProgramaticallySelectedIndexChangedEventIsRaised = function () { + var tabView: tabViewModule.TabView; + var mainPage: pageModule.Page; + var pageFactory = function (): pageModule.Page { + tabView = _createTabView(); + tabView.items = _createItems(10); + mainPage = new pageModule.Page(); + mainPage.content = tabView; + return mainPage; + }; + + helper.navigate(pageFactory); + + var expectedOldIndex = 2; + var expectedNewIndex = 6; + var actualOldIndex; + var actualNewIndex; + + tabView.selectedIndex = expectedOldIndex; + TKUnit.wait(helper.ASYNC); + + tabView.on(tabViewModule.TabView.selectedIndexChangedEvent,(args: tabViewModule.SelectedIndexChangedEventData) => { + actualOldIndex = args.oldIndex; + actualNewIndex = args.newIndex; + }); + + tabView.selectedIndex = expectedNewIndex; + TKUnit.wait(helper.ASYNC); + + try { + TKUnit.assert(actualOldIndex === expectedOldIndex, "Actual: " + actualOldIndex + "; Expected: " + expectedOldIndex); + TKUnit.assert(actualNewIndex === expectedNewIndex, "Actual: " + actualNewIndex + "; Expected: " + expectedNewIndex); + } + finally { + helper.goBack(); + } +} + + export var testWhenNavigatingBackToANonCachedPageContainingATabViewWithAListViewTheListViewIsThere = function () { return; @@ -409,13 +486,13 @@ export function testBindingIsRefreshedWhenTabViewItemIsUnselectedAndThenSelected } export function testLoadedAndUnloadedAreFired_WhenNavigatingAwayAndBack_NoPageCaching() { - testLoadedAndUnloadedAreFired_WhenNavigatingAwayAndBackg(false); + testLoadedAndUnloadedAreFired_WhenNavigatingAwayAndBack(false); } export function testLoadedAndUnloadedAreFired_WhenNavigatingAwayAndBack_WithPageCaching() { - testLoadedAndUnloadedAreFired_WhenNavigatingAwayAndBackg(true); + testLoadedAndUnloadedAreFired_WhenNavigatingAwayAndBack(true); } -function testLoadedAndUnloadedAreFired_WhenNavigatingAwayAndBackg(enablePageCache: boolean) { +function testLoadedAndUnloadedAreFired_WhenNavigatingAwayAndBack(enablePageCache: boolean) { var i: number; var itemCount = 3; var loadedItems = [0, 0, 0]; diff --git a/ui/tab-view/tab-view-common.ts b/ui/tab-view/tab-view-common.ts index 832b1aa27..7bd2e0064 100644 --- a/ui/tab-view/tab-view-common.ts +++ b/ui/tab-view/tab-view-common.ts @@ -39,9 +39,9 @@ var selectedIndexProperty = new dependencyObservable.Property( } export class TabView extends view.View implements definition.TabView, view.AddArrayFromBuilder { - public static itemsProperty = itemsProperty; public static selectedIndexProperty = selectedIndexProperty; + public static selectedIndexChangedEvent = "selectedIndexChanged"; public _addArrayFromBuilder(name: string, value: Array) { if (name === ITEMS) { diff --git a/ui/tab-view/tab-view.android.ts b/ui/tab-view/tab-view.android.ts index a364c4941..58c8557a3 100644 --- a/ui/tab-view/tab-view.android.ts +++ b/ui/tab-view/tab-view.android.ts @@ -451,6 +451,9 @@ export class TabView extends common.TabView { super._onSelectedIndexPropertyChangedSetNativeValue(data); this._setNativeSelectedIndex(data.newValue); + + var args = { eventName: TabView.selectedIndexChangedEvent, object: this, oldIndex: data.oldValue, newIndex: data.newValue }; + this.notify(args); } private _setNativeSelectedIndex(index: number) { diff --git a/ui/tab-view/tab-view.d.ts b/ui/tab-view/tab-view.d.ts index 0945c4f76..79a05954c 100644 --- a/ui/tab-view/tab-view.d.ts +++ b/ui/tab-view/tab-view.d.ts @@ -4,6 +4,7 @@ declare module "ui/tab-view" { import view = require("ui/core/view"); import dependencyObservable = require("ui/core/dependency-observable"); + import observable = require("data/observable"); /** * Represents a tab view entry. @@ -25,6 +26,21 @@ declare module "ui/tab-view" { iconSource?: string; } + /** + * Defines the data for the TabView.selectedIndexChanged event. + */ + export interface SelectedIndexChangedEventData extends observable.EventData { + /** + * The old selected index. + */ + oldIndex: number; + + /** + * The new selected index. + */ + newIndex: number; + } + /** * Represents a tab view. */ @@ -51,5 +67,23 @@ declare module "ui/tab-view" { * Gets the native iOS [UITabBarController](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITabBarController_Class/) that represents the user interface for this component. Valid only when running on iOS. */ ios: UITabBarController; + + /** + * String value used when hooking to the selectedIndexChanged event. + */ + public static selectedIndexChangedEvent: string; + + /** + * A basic method signature to hook an event listener (shortcut alias to the addEventListener method). + * @param eventNames - String corresponding to events (e.g. "propertyChange"). Optionally could be used more events separated by `,` (e.g. "propertyChange", "change"). + * @param callback - Callback function which will be executed when event is raised. + * @param thisArg - An optional parameter which will be used as `this` context for callback execution. + */ + on(eventNames: string, callback: (data: observable.EventData) => void, thisArg?: any); + + /** + * Raised when the selected index changes. + */ + on(event: "selectedIndexChanged", callback: (args: SelectedIndexChangedEventData) => void, thisArg?: any); } } \ No newline at end of file diff --git a/ui/tab-view/tab-view.ios.ts b/ui/tab-view/tab-view.ios.ts index b4dcb5a2a..a84c8d91a 100644 --- a/ui/tab-view/tab-view.ios.ts +++ b/ui/tab-view/tab-view.ios.ts @@ -206,8 +206,12 @@ export class TabView extends common.TabView { } this._ios.selectedIndex = data.newValue; + // We will need to measure and arrange what became this._selectedView this.requestLayout(); + + var args = { eventName: TabView.selectedIndexChangedEvent, object: this, oldIndex: data.oldValue, newIndex: data.newValue }; + this.notify(args); } public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number): void {