在编辑列表时禁用AngularJS中的orderBy

时间:2013-03-08 09:40:34

标签: angularjs angularjs-orderby

在我的输入框列表中应用orderBy后,如果我编辑任何字段,它会立即开始排序,我会失去焦点。我尝试挖掘角度代码并发现他们在orderBy的属性上应用了类似于$ watch的东西,因此每当值更改时,它会对列表进行排序。是否有任何方法可以在编辑时禁用orderBy?我不想让orderBy在编辑文本时对数据进行排序。任何帮助将不胜感激

Here is my plunker

注意:我想使用orderBy&不需要任何替代方法,比如从任何控制器本身对列表进行排序。我只是希望orderBy在页面加载时对列表进行一次排序,然后保持完整。

8 个答案:

答案 0 :(得分:11)

我在使用angular-sortable重新排序的列表中使用了orderBy,并遇到了类似的问题。

我的解决方案是手动执行排序,在初始化页面时调用控制器内的orderBy过滤器,然后在必要时调用它,例如在重新排序列表后调用回调函数。

答案 1 :(得分:8)

您可以覆盖指令,将更新时刻更改为您希望重新排序的时刻。您也可以不使用ng-model并依赖custom directive

This thread讨论覆盖输入指令以更改由tge blur事件触发的模型更新。看看fiddle

虽然您可能会覆盖该指令,但您不应该这样做,而@Liviu T.comments below所解释和示例的最佳解决方案是创建一个删除事件的自定义指令keyup绑定并添加模糊的一个。这是指令代码,这里是Liviu's plunker

app.directive('modelChangeBlur', function() {
    return {
        restrict: 'A',
        require: 'ngModel',
            link: function(scope, elm, attr, ngModelCtrl) {
            if (attr.type === 'radio' || attr.type === 'checkbox') return;

            elm.unbind('input').unbind('keydown').unbind('change');
            elm.bind('blur', function() {
                scope.$apply(function() {
                    ngModelCtrl.$setViewValue(elm.val());
                });         
            });
        }
    };
});
<input type="text" ng-model="variable" model-change-blur/>

不幸的是,由于Angular事件不是名称空间,因此您必须删除以前添加的任何事件。

答案 2 :(得分:2)

关注@CaioToOn但它在Angular 1.2.4(可能是整个1.2.X分支)中中断了。要使它工作,您还需要将custom指令的优先级声明为1(输入指令为0)。 该指令随后变为:

app.directive('modelChangeBlur', function() {
return {
    restrict: 'A',
    priority: 1,
    require: 'ngModel',
        link: function(scope, elm, attr, ngModelCtrl) {
        if (attr.type === 'radio' || attr.type === 'checkbox') return;

        elm.unbind('input').unbind('keydown').unbind('change');
        elm.bind('blur', function() {
            scope.$apply(function() {
                ngModelCtrl.$setViewValue(elm.val());
            });         
        });
    }
};

});

请参阅http://plnkr.co/edit/rOIH7W5oRrijv46f4d9R?p=previewhttps://stackoverflow.com/a/19961284/1196057了解相关优先级问题。

答案 3 :(得分:2)

另一种方法可能是不要放松焦点。如果您的主要问题是失去焦点,那么请将此指令添加到您的输入中,而不是禁用orderBy:

app.directive("keepFocus", ['$timeout', function ($timeout) {
    /*
    Intended use:
        <input keep-focus ng-model='someModel.value'></input>
    */
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function ($scope, $element, attrs, ngModel) {

            ngModel.$parsers.unshift(function (value) {
                $timeout(function () {
                    $element[0].focus();
                });
                return value;
            });

        }
    };
}])

然后只是:

<input keep-focus ng-model="item.name"/>

我知道这并没有直接回答你的问题,但它可能有助于解决潜在的问题。

答案 4 :(得分:0)

没有简单或直接的方法来实现你想要的东西,但有一些选择。你必须在没有ng-model的情况下工作,而是使用blur事件:

JS:

var app = angular.module('myapp', []);

app.controller('MainCtrl', function($scope) {
  $scope.items = [
    { name: 'foo', id: 1, eligible: true },
    { name: 'bar', id: 2, eligible: false },
    { name: 'test', id: 3, eligible: true }
  ];

  $scope.onBlur = function($event, item){
    // Here you find the target node in your 'items' array and update it with new value
    _($scope.items).findWhere({id: item.id}).name = $event.currentTarget.value;
  };
});

app.directive('ngBlur', function($parse) {
  return function ( scope, element, attr ) {
    var fn = $parse(attr.ngBlur);
    element.bind( 'blur', function ( event, arg ) {
      scope.$apply( function(){
        fn(scope, {
          $event : event,
          arg: arg
        });
      });
    });
  };
});

HTML:

<div ng-controller="MainCtrl">
  <div ng-repeat="item in items | orderBy:'name'" >
    <input value="{{item.name}}" ng-blur="onBlur($event, item)"/>
  </div>
</div>

Plunker

但请注意,这会破坏模型与视图之间的双向绑定。

答案 5 :(得分:0)

您可以创建自定义过滤器,并仅在必要时调用它。点击&#39;网格标题&#39;用于排序或在向数组动态添加/删除值之后,或者只需单击按钮(刷新网格)

您需要依赖注入角度过滤器排序过滤器

angular
   .module('MyModule')
   .controller('MyController', ['filterFilter', '$filter', MyContFunc])

     function ExpenseSubmitter(funcAngularFilter, funcAngularFilterOrderBy) {
       oCont = this;
       oCont.ArrayOfData = [{
         name: 'RackBar',
         age: 24
       }, {
         name: 'BamaO',
         age: 48
       }];
       oCont.sortOnColumn = 'age';
       oCont.orderBy = false;
       var SearchObj = {
         name: 'Bama'
       };

       oCont.RefreshGrid = function() {
         oCont.ArrayOfData = funcAngularFilter(oCont.ArrayOfData, SearchObj);
         oCont.ArrayOfData = funcAngularFilterOrderBy('orderBy')(oCont.ArrayOfData, oCont.sortOnColumn, oCont.orderBy);
   }
 }

并使用HTML调用:

<table>
  <thead>
    <tr>
      <th ng-click="oCont.sortOnColumn = 'age'; oCont.RefreshGrid()">Age</th>
      <th ng-click="oCont.sortOnColumn = 'name'; oCont.RefreshGrid()">Name</th>
    </tr>
  </thead>
  <tbody>
    <tr ng-repeat="val in oCont.ArrayOfData">
      <td>{{val.age}}</td>
      <td>{{val.name}}</td>
    </tr>
  </tbody>
</table>

答案 6 :(得分:0)

您可以在编辑时冻结当前排序。说你的HTML看起来像这样:

<tbody ng-repeat="item in items | orderBy:orderBy:reverse">
    <tr ng-click="startEdit()">
      <td>{{item.name}}</td>
    </tr>
</tbody>

在你的控制器中写下:

var savedOrderBy, savedReverse;
$scope.startEdit() = function() {
    $scope.items = $filter('orderBy')($scope.items, $scope.orderby, $scope.reverse);

    for (var i = 0; i < $scope.items.length; ++i) {
        if (i < 9999) { 
            $scope.items[i]['pos'] = ("000" + i).slice(-4); 
        }
    }

    savedOrderBy = $scope.orderBy;
    savedReverse = $scope.reverse;
    $scope.orderBy = 'pos';
    $scope.reverse = false;
};

在用户开始编辑之前,您首先按照当前在页面中显示的顺序对当前项目进行排序。您可以通过使用当前排序参数调用orderBy $ filter()来完成此操作。

然后你查看你现在排序的项目,并添加一个任意属性(这里是“pos”)并将其设置为当前位置。我将其置零以使位置0002在0011之前整理。也许这不是必需的,不知道。

您通常希望记住当前的排序,此处在范围变量“savedOrder”和“savedReverse”中。

最后你告诉angular按新属性“pos”排序,并且表格命令被冻结,因为该属性在编辑时根本不会改变。

完成编辑后,你必须做相反的事情。您可以从范围变量“savedOrder”和“savedReverse”恢复旧的排序:

$scope.endEdit = function() {
    $scope.orderBy = savedOrderBy;
    $scope.reverse = reverse;
};

如果$ scope.items数组的顺序对您很重要,您还必须再次将其排序为原始顺序。

答案 7 :(得分:0)

尝试使用范围变量来更改顺序。在这种情况下,当您打算订购时,您可以调用控制器中的一个功能,将变量顺序值更改为您要订购的字段,并在编辑时重置它。

示例:

<li ng-repeat="item in filtered = (items | filter:search) |  orderBy:order:rever" >

所以这里我们有变量&#34; order&#34;告诉ng-repeat列表必须按哪个字段排序。一个按钮调用控制器中的一个功能来改变&#34;命令&#34;值。

<button type="button" id="orderName" click="changeOrder('item.name')" >Name order </button>

<button type="button" id="orderDate" click="changeOrder('item.date')" >Date order </button>`

然后,在changeOrder函数中

$scope.order = param;

其中&#39; param&#39;是您要订购的字段。如果你不做任何其他事情,那么你将遇到同样的问题,那么,在你为订单变量分配了正确的值后,你就会去

$scope.order = "";

其中重置顺序。 结果是,当按下按钮时,顺序才会生效,然后再次按顺序,除非再次按下按钮。 这可以更改,以便在您完成编辑项目时再次订购。