Skip to content
This repository was archived by the owner on Sep 8, 2020. It is now read-only.

Commit 9641680

Browse files
committed
Merge pull request #155 from thgreasi/master
fix(sortable): race condition when DOM changes inside a digest loop.
2 parents 3b9ebf5 + 36cceb5 commit 9641680

File tree

4 files changed

+41
-13
lines changed

4 files changed

+41
-13
lines changed

bower.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "angular-ui-sortable",
3-
"version": "0.12.2",
3+
"version": "0.12.3",
44
"description": "This directive allows you to jQueryUI Sortable.",
55
"author": "https://github.com/angular-ui/ui-sortable/graphs/contributors",
66
"license": "MIT",

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "angular-ui-sortable",
3-
"version": "0.12.2",
3+
"version": "0.12.3",
44
"description": "This directive allows you to jQueryUI Sortable.",
55
"author": "https://github.com/angular-ui/ui-sortable/graphs/contributors",
66
"license": "MIT",

src/sortable.js

+18-11
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ angular.module('ui.sortable', [])
4242
scope.$watch(attrs.ngModel+'.length', function() {
4343
// Timeout to let ng-repeat modify the DOM
4444
$timeout(function() {
45+
// ensure that the jquery-ui-sortable widget instance
46+
// is still bound to the directive's element
4547
if (!!element.data('ui-sortable')) {
4648
element.sortable('refresh');
4749
}
@@ -174,18 +176,23 @@ angular.module('ui.sortable', [])
174176
};
175177

176178
scope.$watch(attrs.uiSortable, function(newVal /*, oldVal*/) {
177-
angular.forEach(newVal, function(value, key) {
178-
if(callbacks[key]) {
179-
if( key === 'stop' ){
180-
// call apply after stop
181-
value = combineCallbacks(
182-
value, function() { scope.$apply(); });
179+
// ensure that the jquery-ui-sortable widget instance
180+
// is still bound to the directive's element
181+
if (!!element.data('ui-sortable')) {
182+
angular.forEach(newVal, function(value, key) {
183+
if(callbacks[key]) {
184+
if( key === 'stop' ){
185+
// call apply after stop
186+
value = combineCallbacks(
187+
value, function() { scope.$apply(); });
188+
}
189+
// wrap the callback
190+
value = combineCallbacks(callbacks[key], value);
183191
}
184-
// wrap the callback
185-
value = combineCallbacks(callbacks[key], value);
186-
}
187-
element.sortable('option', key, value);
188-
});
192+
193+
element.sortable('option', key, value);
194+
});
195+
}
189196
}, true);
190197

191198
angular.forEach(callbacks, function(value, key) {

test/sortable.spec.js

+21
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,27 @@ describe('uiSortable', function() {
4646
});
4747
});
4848

49+
it('should not try to apply options to a destroyed sortable', function() {
50+
inject(function($compile, $rootScope, $timeout) {
51+
var element;
52+
var childScope = $rootScope.$new();
53+
element = $compile('<div><ul ui-sortable="opts" ng-model="items"><li ng-repeat="item in items">{{ item }}</li></ul></div>')(childScope);
54+
$rootScope.$apply(function() {
55+
childScope.items = ['One', 'Two', 'Three'];
56+
childScope.opts = {
57+
update: function() {}
58+
};
59+
60+
element.remove(element.firstChild);
61+
});
62+
63+
expect(function() {
64+
$timeout.flush();
65+
}).not.toThrow();
66+
67+
});
68+
});
69+
4970
});
5071

5172
});

0 commit comments

Comments
 (0)