在我的输入框列表中应用orderBy
后,如果我编辑任何字段,它会立即开始排序,我会失去焦点。我尝试挖掘角度代码并发现他们在orderBy的属性上应用了类似于$ watch的东西,因此每当值更改时,它会对列表进行排序。是否有任何方法可以在编辑时禁用orderBy?我不想让orderBy在编辑文本时对数据进行排序。任何帮助将不胜感激
注意:我想使用orderBy&不需要任何替代方法,比如从任何控制器本身对列表进行排序。我只是希望orderBy在页面加载时对列表进行一次排序,然后保持完整。
答案 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=preview和https://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>
但请注意,这会破坏模型与视图之间的双向绑定。
答案 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 = "";
其中重置顺序。 结果是,当按下按钮时,顺序才会生效,然后再次按顺序,除非再次按下按钮。 这可以更改,以便在您完成编辑项目时再次订购。