From 4b97ff8a0d4591fdf1ba99d748c078a06d9044e0 Mon Sep 17 00:00:00 2001 From: Martin Staffa Date: Mon, 23 Mar 2015 23:07:04 +0100 Subject: [PATCH] fix(select): don't call $render twice if $viewValue ref changes Credits to @tepez for the fix Closes #11329 --- src/ng/directive/select.js | 4 ++- test/ng/directive/selectSpec.js | 54 +++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/src/ng/directive/select.js b/src/ng/directive/select.js index 66e48bc0ef9d..dee4940688d1 100644 --- a/src/ng/directive/select.js +++ b/src/ng/directive/select.js @@ -200,11 +200,13 @@ var selectDirective = function() { // we have to do it on each watch since ngModel watches reference, but // we need to work of an array, so we need to see if anything was inserted/removed + var lastView, lastViewRef = NaN; scope.$watch(function selectMultipleWatch() { - if (!equals(lastView, ngModelCtrl.$viewValue)) { + if (lastViewRef === ngModelCtrl.$viewValue && !equals(lastView, ngModelCtrl.$viewValue)) { lastView = shallowCopy(ngModelCtrl.$viewValue); ngModelCtrl.$render(); } + lastViewRef = ngModelCtrl.$viewValue; }); // If we are a multiple select then value is now a collection diff --git a/test/ng/directive/selectSpec.js b/test/ng/directive/selectSpec.js index af6262a56166..5be377aa54ee 100644 --- a/test/ng/directive/selectSpec.js +++ b/test/ng/directive/selectSpec.js @@ -841,6 +841,60 @@ describe('select', function() { expect(element).toBeDirty(); }); + + describe('calls to $render', function() { + + var ngModelCtrl; + + beforeEach(function() { + compile( + ''); + + ngModelCtrl = element.controller('ngModel'); + spyOn(ngModelCtrl, '$render').andCallThrough(); + }); + + + it('should call $render once when the reference to the viewValue changes', function() { + scope.$apply(function() { + scope.selection = ['A']; + }); + expect(ngModelCtrl.$render.calls.length).toBe(1); + + scope.$apply(function() { + scope.selection = ['A', 'B']; + }); + expect(ngModelCtrl.$render.calls.length).toBe(2); + + scope.$apply(function() { + scope.selection = []; + }); + expect(ngModelCtrl.$render.calls.length).toBe(3); + }); + + + it('should call $render once when the viewValue deep-changes', function() { + scope.$apply(function() { + scope.selection = ['A']; + }); + expect(ngModelCtrl.$render.calls.length).toBe(1); + + scope.$apply(function() { + scope.selection.push('B'); + }); + expect(ngModelCtrl.$render.calls.length).toBe(2); + + scope.$apply(function() { + scope.selection.length = 0; + }); + expect(ngModelCtrl.$render.calls.length).toBe(3); + }); + + }); + });