16

入力ボックスのリストに適用orderByした後、フィールドを編集するとすぐに並べ替えが開始され、フォーカスが失われます。angularコードを掘り下げようとしたところ、orderByの属性に$watchのようなものが適用されていることがわかりました。そのため、値が変更されるたびにリストがソートされます.編集中にorderByを無効にする方法はありますか? テキストの編集中に orderBy でデータをソートさせたくありません。どんな助けでも大歓迎です

これが私のプランカーです

:orderByを使用したいのですが、コントローラー自体からリストをソートするなどの代替手段は必要ありません。ページの読み込み時に orderBy でリストを一度並べ替えてから、そのままにしておきたいだけです。

4

8 に答える 8

11

angular-sortableorderByを使用して並べ替えることができるリストを使用していましたが、同様の問題に遭遇しました。

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

于 2014-03-06T10:42:30.643 に答える
8

ディレクティブをオーバーライドして、更新の瞬間を並べ替えたい瞬間に変更できます。また、カスタム ディレクティブng-modelを使用して依存することもできません。

このスレッドでは、input ディレクティブをオーバーライドして、モデルの更新が tgeblurイベントによってトリガーされるように変更する方法について説明します。フィドルを見てください。

ディレクティブをオーバーライドすることはできますが、これを行うべきではありません。以下のコメントで@Liviu T.によって説明および例示されているように、最良の解決策は、イベント キーアップ バインディングを削除し、ぼかしバインディングを追加するカスタム ディレクティブを作成することです。 . これがディレクティブ コードで、これがLiviu の 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 イベントは名前空間ではないため、以前に追加したイベントを削除する必要があります。

于 2013-03-08T11:30:50.683 に答える
3

別のアプローチは、最初から集中力を失わないことかもしれません。主な問題がフォーカスを失うことである場合は、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"/>

これがあなたの質問に直接答えるものではないことはわかっていますが、根本的な問題の解決に役立つ可能性があります.

于 2015-08-10T21:15:58.217 に答える
2

次の @CaioToOn は機能しますが、Angular 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を参照してください。

于 2013-12-10T21:20:42.457 に答える
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>

プランカー

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

于 2013-03-08T11:54:39.090 に答える
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」の現在の順序を覚えておきたいと思います。

そして最後に、その新しいプロパティ「pos」でソートするようにangularに指示すると、編集中にそのプロパティが変更されないため、テーブルの順序が固定されます。

編集が終わったら、反対のことをしなければなりません。スコープ変数「savedOrder」と「savedReverse」から古い順序を復元します。

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

$scope.items 配列の順序が重要な場合は、元の順序に再度並べ替える必要があります。

于 2015-11-19T15:10:43.437 に答える