2013-03-08 7 views
15

orderByを入力ボックスのリストに適用した後、フィールドを編集すると、すぐにソートが開始され、フォーカスが緩やかになります。私は角度コードを掘り下げようとしましたが、orderByの属性に$ watchのようなものを適用したことがわかりました。値が変わるたびにリストをソートします。編集中にorderByを無効にする方法はありますか?私は、テキストを編集中にorderByデータをソートしたいと思っていません。すべてのヘルプは理解されるであろうリストを編集中にAngularJSのorderByを無効にする

Here is my plunker

:私はORDERBY &を使用する場合は、任意のコントローラ自体からリストを並べ替えのような任意の代替を必要としません。私はorderByがページロード時に一度リストをソートしてからかなりのままにしておきたいだけです。

+1

サーバーが自分のデータを送信するときに、ソートしたいフィールドがある追加の列 'sortBy'が含まれている場合、ng-repeatはorderByのためにそれを使用します。このフィールドは編集中ではないので、サーバーから行が戻ってくるまで変更されません。私。レコードを "保存"すると、$ scope内の同じ行を置き換えるsortByを含むデータベースから返されたデータがフェッチされ、編集が完了した後でのみページのソートが更新されます。 –

答えて

8

リオーダリングを行う瞬間に更新の瞬間を変更するために、ディレクティブを上書きすることができます。 ng-modelを使用せず、custom directiveに頼ることもできます。

This threadは、tge blurイベントによってトリガされるモデル更新を変更する入力ディレクティブをオーバーライドする方法について説明します。 fiddleをご覧ください。

@Liviu T.comments belowに説明されているように、この最適化ソリューションは、イベントキーアップバインディングを削除し、ぼかし1を追加するカスタムディレクティブを作成することです。ここでディレクティブコードがあり、ここで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/> 

、角度のイベントが名前空間ではないとして、あなたが以前に追加されたイベントを削除する必要があります。

+2

私はあなたがオーバーライドしないことを提案しますが、あなたはそれが必要な場所でのみ動作を可能にする新しい指令を追加してくださいhttp://plnkr.co/edit/yoUmEUMMzecNlbKmtgDq?p=preview –

+0

良い解決策ですが、既に存在するものを上書きします。 keydownイベントであっても、ビューとのバインドを解除したくない場合は –

+0

私は同意し、@ LiviuTに対応するように質問を更新しました。溶液。残念ながら、 'keydown'更新を避ける唯一の方法は、既に要素にバインドされているイベントを削除することです。 Liviuの解決策の良い点は、デフォルトディレクティブが使用されている他の瞬間に負けないことです。 –

0

あなたが望むものを達成するための簡単な方法はありませんが、いくつかの選択肢があります。

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をあなたはNG-モデルなしで動作し、代わりにblurイベントを使用する必要があります。

ただし、モデルとビューの間の双方向バインディングが壊れることに注意してください。

+0

私は私のページ内の他の要素とバインドしているので、入力ボックスをぼかすまでこれらの変更は反映されないと思います。右? orderByを無効にしたり編集したりして、ページをリロードしたり、ボタンを使用して並べ替えを適用するまでは、変更が反映されないようにすれば、より良いものになるでしょう。あなたのソリューションは間違いなく良いですが、私はng-modelでハックしたくありません。あなたが理解してくれることを願っています –

+0

'orderBy'フィルタは実際に変更を監視していません。これはng-repeatディレクティブで、 'items'配列を監視し、あなたのngモデルが変更されるとすぐにそれを繰り返します。ですから、私が提案したやり方にするか、カスタムng-repeat指令を作成して変更を監視するのではなく、他の(明示的な)方法でトリガされるかもしれません。 – Stewie

2

@CaioToOnの後には動作しますが、角度1.2.4(場合によっては1.2.Xブランチ全体)でブレークします。それを動作させるには、カスタムディレクティブの優先順位を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を参照してください。

+0

これはいいですが、グリッドにチェックボックスがあり、ユーザーがアイテムをチェックすると、その行が新しいソートされた場所に移動します。私はそれについて何をすることができますか? –

10

私はangular-sortableを使用して並べ替えることができるリストにorderByを使用していましたが、同様の問題が発生しました。

私が解決したのは、ページが初期化されたときにコントローラ内のorderByフィルタを呼び出し、必要に応じて、たとえばリストを並べ替えた後にコールバック関数で呼び出すことでした。

+2

その例を教えてください。 –

+3

公式文書には例があります:https://docs.angularjs.org/api/ng/filter/orderBy。 'var orderBy = $ filter( 'orderBy');'を検索してください。 '$ filter'を注入することを忘れないでください。 – Maxence

0

カスタムフィルタを作成し、必要なときにのみ呼び出すことができます。あなたは、ソートのために、または動的配列に値を追加/削除した後、「グリッド・ヘッダー」をクリックし、または単にボタン(更新グリッド)をクリックする例

あなたは注入する角度フィルタソートフィルタ

を依存関係する必要があります
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> 
2

異なるアプローチ。あなたの主な問題は、代わりに[並べ替えを無効にするのあなたの失うの焦点は、その後、あなたの入力には、このディレクティブを追加することである場合:

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"/> 

私は、これは直接あなたの質問に答えていない知っています根本的な問題を解決するのに役立つかもしれません。

+0

これは役に立ちました。私の状況を改善してくれました。ありがとうございました。ただし、ソートcolにチェックボックスがあり、それをチェックすると、そのアイテムは適切な順序でシュートされます。任意のアイデアを改善する方法は? –

0

編集中に現在の順序を固定することができます。あなたが書いたあなたのコントローラで

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

:あなたのHTMLは次のようになりますと言う

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"に記憶します。

最後にangleを新しいプロパティ "pos"で並べ替えるように指示し、テーブルの順序が固定されているのは編集中に変更されないためです。

編集が完了したら、その逆の操作を行う必要があります。あなたのための$ scope.items配列の順番には、あなたはまた、元の順序に再びそれをソートする必要があります場合は

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

:あなたは、スコープ変数「savedOrder」と「savedReverse」から古い秩序を回復します。

0

スコープ変数を使用して順序を変更してみてください。この場合、注文するときに、可変注文値を注文する項目に変更する機能を呼び出し、編集中はその項目をリセットします。

例:

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

そこでここでは、リストが注文しなければならない分野でNGリピートを伝えるために、変数「注文」を持っています。ボタンは、コントローラ内で「順序」値を変更する関数を呼び出します。

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

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

そして、 'paramは' あなたがで注文したいフィールドですchangeOrder機能

$scope.order = param; 

インチあなたが何かをしない場合、あなたはあなたが持っていた同じ問題を持ってしようとしているあなたは順序変数に正しい値を割り当てた後、そうして、あなたは順序をリセットし

$scope.order = ""; 

を行きます。 結果は、ボタンを押したときに順序が有効になるだけで、ボタンをもう一度押さない限り、再度注文するということです。 これは変更することができます。たとえば、必要に応じてアイテムの編集が完了したら、再度注文することができます。

関連する問題