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

fix(sortable): race condition when DOM changes inside a digest loop. #155

Merged
merged 2 commits into from
Apr 10, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion bower.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "angular-ui-sortable",
"version": "0.12.2",
"version": "0.12.3",
"description": "This directive allows you to jQueryUI Sortable.",
"author": "https://github.com/angular-ui/ui-sortable/graphs/contributors",
"license": "MIT",
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "angular-ui-sortable",
"version": "0.12.2",
"version": "0.12.3",
"description": "This directive allows you to jQueryUI Sortable.",
"author": "https://github.com/angular-ui/ui-sortable/graphs/contributors",
"license": "MIT",
Expand Down
29 changes: 18 additions & 11 deletions src/sortable.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ angular.module('ui.sortable', [])
scope.$watch(attrs.ngModel+'.length', function() {
// Timeout to let ng-repeat modify the DOM
$timeout(function() {
// ensure that the jquery-ui-sortable widget instance
// is still bound to the directive's element
if (!!element.data('ui-sortable')) {
element.sortable('refresh');
}
Expand Down Expand Up @@ -174,18 +176,23 @@ angular.module('ui.sortable', [])
};

scope.$watch(attrs.uiSortable, function(newVal /*, oldVal*/) {
angular.forEach(newVal, function(value, key) {
if(callbacks[key]) {
if( key === 'stop' ){
// call apply after stop
value = combineCallbacks(
value, function() { scope.$apply(); });
// ensure that the jquery-ui-sortable widget instance
// is still bound to the directive's element
if (!!element.data('ui-sortable')) {
angular.forEach(newVal, function(value, key) {
if(callbacks[key]) {
if( key === 'stop' ){
// call apply after stop
value = combineCallbacks(
value, function() { scope.$apply(); });
}
// wrap the callback
value = combineCallbacks(callbacks[key], value);
}
// wrap the callback
value = combineCallbacks(callbacks[key], value);
}
element.sortable('option', key, value);
});

element.sortable('option', key, value);
});
}
}, true);

angular.forEach(callbacks, function(value, key) {
Expand Down
21 changes: 21 additions & 0 deletions test/sortable.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,27 @@ describe('uiSortable', function() {
});
});

it('should not try to apply options to a destroyed sortable', function() {
inject(function($compile, $rootScope, $timeout) {
var element;
var childScope = $rootScope.$new();
element = $compile('<div><ul ui-sortable="opts" ng-model="items"><li ng-repeat="item in items">{{ item }}</li></ul></div>')(childScope);
$rootScope.$apply(function() {
childScope.items = ['One', 'Two', 'Three'];
childScope.opts = {
update: function() {}
};

element.remove(element.firstChild);
});

expect(function() {
$timeout.flush();
}).not.toThrow();

});
});

});

});