diff --git a/platform/commonUI/general/bundle.json b/platform/commonUI/general/bundle.json index b8213f8c77..59e890f8a9 100644 --- a/platform/commonUI/general/bundle.json +++ b/platform/commonUI/general/bundle.json @@ -49,7 +49,7 @@ { "key": "ViewSwitcherController", "implementation": "controllers/ViewSwitcherController.js", - "depends": [ "$scope" ] + "depends": [ "$scope", "$timeout" ] }, { "key": "BottomBarController", diff --git a/platform/commonUI/general/src/controllers/ViewSwitcherController.js b/platform/commonUI/general/src/controllers/ViewSwitcherController.js index a7942fe627..05fec1bd1a 100644 --- a/platform/commonUI/general/src/controllers/ViewSwitcherController.js +++ b/platform/commonUI/general/src/controllers/ViewSwitcherController.js @@ -13,7 +13,7 @@ define( * of applicable views for a represented domain object. * @constructor */ - function ViewSwitcherController($scope) { + function ViewSwitcherController($scope, $timeout) { // If the view capability gets refreshed, try to // keep the same option chosen. function findMatchingOption(options, selected) { @@ -32,10 +32,12 @@ define( // Get list of views, read from capability function updateOptions(views) { - $scope.ngModel.selected = findMatchingOption( - views || [], - ($scope.ngModel || {}).selected - ); + $timeout(function () { + $scope.ngModel.selected = findMatchingOption( + views || [], + ($scope.ngModel || {}).selected + ); + }, 0); } // Update view options when the in-scope results of using the diff --git a/platform/commonUI/general/test/controllers/ViewSwitcherControllerSpec.js b/platform/commonUI/general/test/controllers/ViewSwitcherControllerSpec.js index af0b99aa88..1895fb5302 100644 --- a/platform/commonUI/general/test/controllers/ViewSwitcherControllerSpec.js +++ b/platform/commonUI/general/test/controllers/ViewSwitcherControllerSpec.js @@ -10,12 +10,15 @@ define( describe("The view switcher controller", function () { var mockScope, + mockTimeout, controller; beforeEach(function () { mockScope = jasmine.createSpyObj("$scope", [ "$watch" ]); + mockTimeout = jasmine.createSpy("$timeout"); + mockTimeout.andCallFake(function (cb) { cb(); }); mockScope.ngModel = {}; - controller = new ViewSwitcherController(mockScope); + controller = new ViewSwitcherController(mockScope, mockTimeout); }); it("watches for changes in applicable views", function () { @@ -71,6 +74,19 @@ define( expect(mockScope.ngModel.selected).not.toEqual(views[1]); }); + // Use of a timeout avoids infinite digest problems when deeply + // nesting switcher-driven views (e.g. in a layout.) See WTD-689 + it("updates initial selection on a timeout", function () { + // Verify precondition + expect(mockTimeout).not.toHaveBeenCalled(); + + // Invoke the watch for set of views + mockScope.$watch.mostRecentCall.args[1]([]); + + // Should have run on a timeout + expect(mockTimeout).toHaveBeenCalled(); + }); + }); } ); \ No newline at end of file