AngularJS列表之间的拖放打破1.2

时间:2014-02-18 23:36:10

标签: javascript jquery-ui angularjs

我一直在使用AngularJS和jQuery UI的拖放实现:

http://www.smartjava.org/examples/dnd/double.html

使用AngularJS 1.0.8,它可以完美运行。在1.2.11中,它没有。

使用AngularJS 1.2并将项目从左侧列表拖动到右侧列表时,目标列表的模型会正确更新。但是DOM没有正确更新。以下是从示例中使用的指令:

app.directive('dndBetweenList', function($parse) {

  return function(scope, element, attrs) {

    // contains the args for this component
    var args = attrs.dndBetweenList.split(',');
    // contains the args for the target
    var targetArgs = $('#'+args[1]).attr('dnd-between-list').split(',');

    // variables used for dnd
    var toUpdate;
    var target;
    var startIndex = -1;

    // watch the model, so we always know what element
    // is at a specific position
    scope.$watch(args[0], function(value) {
        toUpdate = value;
    },true);

    // also watch for changes in the target list
    scope.$watch(targetArgs[0], function(value) {
        target = value;
    },true);

    // use jquery to make the element sortable (dnd). This is called
    // when the element is rendered
    $(element[0]).sortable({
        items:'li',
        start:function (event, ui) {
            // on start we define where the item is dragged from
            startIndex = ($(ui.item).index());
        },
        stop:function (event, ui) {
            var newParent = ui.item[0].parentNode.id;

            // on stop we determine the new index of the
            // item and store it there
            var newIndex = ($(ui.item).index());
            var toMove = toUpdate[startIndex];

            // we need to remove him from the configured model
            toUpdate.splice(startIndex,1);

            if (newParent == args[1]) {
                // and add it to the linked list
                target.splice(newIndex,0,toMove);
            }  else {
                toUpdate.splice(newIndex,0,toMove);
            }

            // we move items in the array, if we want
            // to trigger an update in angular use $apply()
            // since we're outside angulars lifecycle
            scope.$apply(targetArgs[0]);
            scope.$apply(args[0]);
        },
        connectWith:'#'+args[1]
    })
  }
});

是否需要更新某些内容才能使其与Angular 1.2一起正常使用?我觉得它与scope.$apply有关,但我不确定。

1 个答案:

答案 0 :(得分:1)

我认为这是一个较旧的问题,但我最近遇到了与拖放示例完全相同的问题。我不知道角度1.0.8和1.2之间有什么变化,但它似乎是导致DOM问题的摘要周期。 scope.$apply会触发摘要周期,但scope.$apply本身并不是问题。导致循环的任何事情都可能导致DOM与模型失去同步。

我能够使用ui.sortable指令找到问题的解决方案。我使用的具体分支在这里:https://github.com/angular-ui/ui-sortable/tree/angular1.2。我还没有和其他分支机构一起测试过。

您可以在此处查看工作示例:

http://plnkr.co/edit/atoDX2TqZT654dEicqeS?p=preview

使用ui-sortable解决方案,'dndBetweenList'指令被ui-sortable指令替换。然后有一些变化。

在HTML

<div class="row">
<div class="span4 offset2">
      <ul ui-sortable="sortableOptions" ng-model="source" id="sourceList"  ng-class="{'minimalList':sourceEmpty()}" class="connector">
        <li class="alert alert-danger nomargin" ng-repeat="item in source">{{item.value}}</li>
      </ul>
    </div>
<div class="span4">
      <ul ui-sortable="sortableOptions" id="targetList" ng-model="model" ng-class="{'minimalList':sourceEmpty()}" class="connector">
        <li class="alert alert-info nomargin" ng-repeat="item in model">{{item.value}}</li>
      </ul>
    </div>
  </div>

请注意,不再需要dnd-between-list指令,并将其替换为ui-sortable。

在模块中注入ui-sortable,并在控制器中指定可排序的选项。 sortable接受与jquery sortable相同的选项。

app.js

var app = angular.module('dnd', ['ui.sortable']); 

CTRL-dnd.js

$scope.sortableOptions  = {
    connectWith: '.connector'
}

仅显示控制器的添加内容。请注意,我在ul上添加了一个.connector类。在sortable中,我使用.connector作为connectWith选项。