3

我在 AngularUI 中使用 Sortable 来管理多个可排序列表。我已经让它工作到可以轻松地在列表之间移动项目并相应地更新其相应模型的地步。但是,如果我包含查询过滤器,如果发生以下情况,我会遇到一些问题:

  1. 用户输入不是列表第一个条目的项目的搜索字段。
  2. 用户将过滤结果中的第一项从一个列表移动到另一个列表。
  3. 它似乎有效,直到查询被清除并显示初始列表。虽然您似乎在应用查询时移动了条目,但您会注意到在它被清除后,未过滤数组中的第一个条目被移动了。

拖放时,Sortable 似乎没有考虑过滤器。这是相关的HTML:

  <p>Search: <input ng-model="query" /></p>
  <div class="column-wrapper">
    <ul ui-sortable="sortableTemplates" ng-model="list1" id="sortable1" class="connectedSortable">
      <li ng-repeat="item in list1|filter:query" class="itemBox">{{item.name}}</li>
    </ul>
    <ul ui-sortable="sortableTemplates" ng-model="list2" id="sortable2" class="connectedSortable">
      <li ng-repeat="item in list2|filter:query" class="itemBox">{{item.name}}</li>
    </ul>
  </div>

以及对应的JS:

var app = angular.module('myApp', ['ui.sortable']);
app.controller('test', function($scope) {

$scope.list1 = [
    {name: 'ABC'},
    {name: 'DEF'},
    {name: 'GHI'}
];

$scope.list2 = [
    {name: 'JKL'},
    {name: 'MNO'},
    {name: 'QRS'}
];

$scope.sortableTemplates = {
    connectWith: '.connectedSortable'
}

});

它在 Plunker 上运行。

要重现该问题,您可以尝试搜索GHI,然后转到GHIlist2。然后,清除搜索框。ABC是实际移动到 list2 的那个(因为它是该数组中的第一个元素),并GHI保留在 list one 中。

有没有办法让 Angular 过滤器进行排序,以便在列表之间排序时保留原始索引?

(我是使用 Angular 和 JQueryUI 的新手,所以答案可能非常明显。我发现了类似的问题,但似乎没有直接解决这个问题。)

4

1 回答 1

3

正如您所说的 ui-sortable 正在使用元素索引在列表之间移动它,因此当您移动过滤列表中的第一项时,它会移动原始列表中的第一项。解决此问题的一种方法不是过滤您的列表,而是隐藏您不想移动的项目,而不是像 ng-repeat 中的过滤器那样创建一个新列表。所以在你的html中:

<li ng-repeat="item in list1" class="itemBox" ng-show="visible(item)">{{item.name}}</li>

ng-show 将根据 $scope.visible(item) 返回 true 或 false 来显示或隐藏元素。因此,我们在控制器中创建了一个函数,如果我们想查看元素,则返回 true,即它没有被过滤掉,如果它被过滤掉,则返回 false。

$scope.visible=function(item){
  //create an array containing all of the elements in both lists
  var lists=$scope.list1.concat($scope.list2);
  // filter this list using our search term
  var filteredItems=$filter('filter')(lists, $scope.query);
  //if there are no matching items left in our list then return false
  if (filteredItems.length===0){return false;}
  //see if the current item is in the filtered list   
  if (($filter('filter')(filteredItems,item)).length===1){
     return true;
  } else {
     return false;
  }
}

我在http://plnkr.co/edit/JCQdcP?p=preview创建了一个 plunker

于 2013-09-29T08:59:14.917 回答