web-dev-qa-db-ja.com

AngularJS ngTableを使用したカスタムフィルター

私はngTableを使用してテーブルを構築しようとしていますが、 ngTableページの例 で説明されているものとは異なるカスタムフィルタリングを使用しています。

適切なフィルタリングが必要ですが、ngTableでフィルターセレクターをレンダリングしたくありません。自分で(表の上に)レンダリングし、「getData()」メソッドでそれらを参照したいのですが。

前に参照した例では、その機械の動作については説明していません。各 "td"要素の "filter"プロパティで何を指定する必要があるのか​​正確にはわかりません。 AngularJSの$ filter関数の基本的な構文は理解していますが、これを使用してngTableが何をしているのかはわかりません。 1つの例から、「等しい」チェックしか実行できないように見えます。これは、関連付けられた列の値がフィルター値と等しい行のみを選択することになります。それは私が必要とするものではありません。

テーブルにいくつかの列があります。それらの2つは「キー」と「失敗」と呼ばれ、それぞれ文字列とブール値です。これらのフィルターフィールドをテーブルの上にレンダリングするとき、「失敗した」フィルターのカスタムラベルが必要です。 「キー」列のフィルタリングは、フィルター値を「キー」値のサブストリングと一致させる必要があります。たとえば、「abc」、「abac」、および「def」のキー値がある場合、「a」のフィルター値により、最初の2つのエントリが表示され、「def」エントリは表示されません。

更新:

これに関連して、私はこのようなことをする方法を理解できるといいのですが:

「標準の」angularjsフィルターを使用して、次のようにテーブル要素にngRepeat式があるとします。

"item in $data | customfilter:param | anothercustomfilter:param"

これらのフィルターは「getData()」メソッドから取得した1つのページスライスにのみ適用されるため、これはうまく機能しないことがわかっています。 「getData()」メソッドで実行できるようにしたいのは、パラメーター式を含むフィルターチェーン全体にアクセスし、別の配列をそれに渡すだけです。ページスライス。

同時に、私は通常の処理でそのフィルターチェーンを実行することにより、angularjsのフィルタリング自体を「オフにする」ことができる必要があります。

これは難しいように聞こえますが、現在のAPIではHTMLとJavaScriptの間の多くの結合が必要であることがわかりました。 HTMLが希望のフィルタリングを指定でき、JavaScriptがそのフィルターチェーン全体を使用するだけで、ページスライスだけでなく、データリスト全体で使用するのは、すばらしいことです。

更新:

ここに私のHTMLからの関連する抜粋があります:

<label for="keysFilter">Filter Keys:</label>
<input id="keysFilter" type="text" ng-model="keysFilter"/>
<label for="showOnlyFailed">Show only queries that failed?</label>
<input id="showOnlyFailed" type="checkbox" ng-model="showOnlyFailed"/>
<table ng-table="tableParams" table-pagination="custom/pages" class="table">
<tr ng-repeat="queryInfo in $data"> <!--  | filterFailed:showOnlyFailed | filterMatchingKeys:keysFilter -->

これが私のtableParamsコードです:

$scope.tableParams  = new ngTableParams({
    page: 1,
    count: 10,
    sorting: {
        lastRun: 'desc'
    }
},
{
    debugMode: true,
    total:  $scope.completedQueries.length,
    getData:    function($defer, params) {
        var orderedData = params.sorting() ?
                $filter('orderBy')($scope.completedQueries, params.orderBy()) :
                data;
        orderedData = $filter('filterFailed')(orderedData, $scope.showOnlyFailed);
        orderedData = $filter('filterMatchingKeys')(orderedData, $scope.keysFilter);

        params.total(orderedData.length);
        $defer.resolve(orderedData.slice((params.page() - 1) * params.count(),
                                                     params.page() * params.count()));
    }
});

私が使用したのは、このngTableに "$ data"リストを使用せず、 "completedQueries"リストを繰り返し処理することです。そのように機能した場合、「失敗したクエリのみを表示」チェックボックスをクリックするか、「keysFilter」入力フィールドにテキストを入力すると、リストはすぐに変更されます。

ただし、「$ data」リストを使用しているため、これらのフィールドのいずれかを変更しても何も起こりません。実際、これらのフィールドの両方に$ watch-esを追加しただけで、どちらも起動しません。ただし、これらのフィールドのいずれかに変更を加えると、テーブルデータが再評価されていることがわかります。これは、2つの列にミリ秒の値であると予想されるデータがあり、これらの列に値を変換するカスタムフィルターがあるためです。 「30秒前」や「2分前」などの「時間前」の英語表現。これらの入力フィールドの1つを変更するたびに、テーブル内のそれらの式が変更されますが、それでもまだ実行されません。適切なフィルタリング。

問題がある場合は、スコープに追加した$ watch-esを次に示します。これらは決して発砲しないようです:

    $scope.$watch("showOnlyFailed", function() {
    $scope.tableParams.reload();
});

$scope.$watch("keysFilter", function() {
    $scope.tableParams.reload();
});

これらをコメント化すると、「getData()」メソッドを実行した後に次のエラーが表示されることに注意してください。

Error: settings.$scope is null
@http://localhost:8000/js/diag/libs/ng-table.src.js:411
qFactory/defer/deferred.promise.then/wrappedCallback@http://ajax.googleapis.com/ajax/libs/angularjs/1.2.14/angular.js:11046
qFactory/ref/<.then/<@http://ajax.googleapis.com/ajax/libs/angularjs/1.2.14/angular.js:11132
Scope.prototype.$eval@http://ajax.googleapis.com/ajax/libs/angularjs/1.2.14/angular.js:12075
Scope.prototype.$digest@http://ajax.googleapis.com/ajax/libs/angularjs/1.2.14/angular.js:11903
Scope.prototype.$apply@http://ajax.googleapis.com/ajax/libs/angularjs/1.2.14/angular.js:12179
bootstrap/doBootstrap/<@http://ajax.googleapis.com/ajax/libs/angularjs/1.2.14/angular.js:1341
invoke@http://ajax.googleapis.com/ajax/libs/angularjs/1.2.14/angular.js:3762
bootstrap/doBootstrap@http://ajax.googleapis.com/ajax/libs/angularjs/1.2.14/angular.js:1340
bootstrap@http://ajax.googleapis.com/ajax/libs/angularjs/1.2.14/angular.js:1353
angularInit@http://ajax.googleapis.com/ajax/libs/angularjs/1.2.14/angular.js:1301
@http://ajax.googleapis.com/ajax/libs/angularjs/1.2.14/angular.js:21048
n.Callbacks/j@http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js:2
n.Callbacks/k.fireWith@http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js:2
.ready@http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js:2
K@http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js:2
http://ajax.googleapis.com/ajax/libs/angularjs/1.2.14/angular.js
Line 9509

これは、関連するコードブロックです。

            $defer.promise.then(function (data) {
            settings.$loading = false;
            log('ngTable: current scope', settings.$scope);
            if (settings.groupBy) {
                self.data = settings.$scope.$groups = data;
            } else {
                self.data = settings.$scope.$data = data; // line 411
            }
            settings.$scope.pages = self.generatePagesArray(self.page(), self.total(), self.count());
        });

更新:

これが私の plunkr です。これは、外部フィルターフィールドの変更が機能しないことを示しています。また、これを修正するために2つの$ watch-esがコメント化されています。それらをコメントすると、ng-table内で、スコープがnullであるというエラーが発生します。

更新:

$ watch-esに「newvalue、oldvalue」パラメーターを追加してみました(plunkrを更新しました)。現在、フィールドへの変更により、テーブルが更新されています。残念ながら、ng-tableの411行目でもそのスタックトレースを取得しています。

12
David M. Karr

作成した時計やカスタムフィルターは必要ありません。実際には、角度の「フィルター」フィルターは非常に強力です。

必要なのは、アイテムのフィールドに一致するメンバーを持つフィルター値を追跡するオブジェクトを作成することだけです。このようなもの。

_$scope.filter = {
    key: undefined,
    failed: undefined
}
_

その後、params.filter()を使用してgetDataコールバック内に戻すことができます。私はあなたの ここのプランカー を更新しました。以下のサンプルも確認できます。

_var app = angular.module('main', ['ngTable']);

app.controller('MainCtrl', function($scope, $http, $filter, ngTableParams) {

    $scope.completedQueries = [{"key":"abc000","lastRun":123,"lastSuccessfulTime":9999,"elapsedTime":456,"rows":10,"failed":false},{"key":"abc001","lastRun":1234,"lastSuccessfulTime":9999,"elapsedTime":456,"rows":10,"failed":false},{"key":"abc002","lastRun":111111111,"lastSuccessfulTime":9999,"elapsedTime":456,"rows":10,"failed":true},{"key":"abc003","lastRun":123,"lastSuccessfulTime":9999,"elapsedTime":456,"rows":10,"failed":false},{"key":"abc004","lastRun":1234,"lastSuccessfulTime":9999,"elapsedTime":456,"rows":10,"failed":true},{"key":"abc005","lastRun":111111111,"lastSuccessfulTime":9999,"elapsedTime":456,"rows":10,"failed":false},{"key":"abc006","lastRun":123,"lastSuccessfulTime":9999,"elapsedTime":456,"rows":10,"failed":false},{"key":"abc007","lastRun":1234,"lastSuccessfulTime":9999,"elapsedTime":456,"rows":10,"failed":false},{"key":"abc008","lastRun":111111111,"lastSuccessfulTime":9999,"elapsedTime":456,"rows":10,"failed":false},{"key":"abc009","lastRun":123,"lastSuccessfulTime":9999,"elapsedTime":456,"rows":10,"failed":false},{"key":"abc010","lastRun":1234,"lastSuccessfulTime":9999,"elapsedTime":456,"rows":10,"failed":false},{"key":"abc011","lastRun":111111111,"lastSuccessfulTime":9999,"elapsedTime":456,"rows":10,"failed":false},{"key":"abc012","lastRun":123,"lastSuccessfulTime":9999,"elapsedTime":456,"rows":10,"failed":true},{"key":"abc013","lastRun":1234,"lastSuccessfulTime":9999,"elapsedTime":456,"rows":10,"failed":false},{"key":"abc014","lastRun":111111111,"lastSuccessfulTime":9999,"elapsedTime":456,"rows":10,"failed":false},{"key":"abc015","lastRun":123,"lastSuccessfulTime":9999,"elapsedTime":456,"rows":10,"failed":true},{"key":"abc016","lastRun":1234,"lastSuccessfulTime":9999,"elapsedTime":456,"rows":10,"failed":false},{"key":"abc017","lastRun":111111111,"lastSuccessfulTime":9999,"elapsedTime":456,"rows":10,"failed":false}];
    $scope.filter = {
        key: undefined,
        failed: undefined
    };
    $scope.tableParams =  new ngTableParams({
        page: 1,
        count: 10,
        filter: $scope.filter
    }, {
        debugMode: true,
        total: $scope.completedQueries.length,
        getData: function($defer, params) {
            var orderedData = params.sorting() ? $filter('orderBy')($scope.completedQueries, params.orderBy()) : data;
            orderedData = $filter('filter')(orderedData, params.filter());
            params.total(orderedData.length);
            $defer.resolve(orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count()));
        }
    });
});_
_<link href="https://cdnjs.cloudflare.com/ajax/libs/ng-table/0.3.3/ng-table.min.css" rel="stylesheet"/>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ng-table/0.3.3/ng-table.min.js"></script>
<div  ng-app="main"  ng-controller="MainCtrl">
  <label for="keysFilter">Filter Keys:</label>
  <input id="keysFilter" type="text" ng-model="filter.key"/>
  <label for="showOnlyFailed">Show only queries that failed?</label>
  <input id="showOnlyFailed" type="checkbox" ng-model="filter.failed"/>
  <br/>
  <table ng-table="tableParams" class="table">
    <tr ng-repeat="queryInfo in $data">
        <td data-title="'Key'" sortable="'key'">{{queryInfo.key}}</td>
        <td data-title="'Last Run'" sortable="'lastRun'">{{queryInfo.lastRun}}</td>
        <td data-title="'Last Successful Run'" sortable="'lastSuccessfulRun'">{{queryInfo.lastSuccessfulRun}}</td>
        <td data-title="'Elapsed Time'" sortable="'elapsedTime'">{{queryInfo.elapsedTime}} ms</td>
        <td data-title="'Rows'" sortable="'rows'">{{queryInfo.rows}}</td>
        <td data-title="'Failed'" sortable="'failed'">{{queryInfo.failed}}</td>
        <td data-title="''"><button class="btn">Detail</button></td>
    </tr>
  </table> 
<div>_
8
cleftheris

ng-table自体に問題が発生しているようです。これは、あまりサポートされていないサードパーティのライブラリです。

これの証拠として、200以上の未解決の問題と1,200の星(1:6)があるGithubページを確認してください。

https://github.com/esvit/ng-table

これをD3.jsのようなライブラリと比較してください。このライブラリは、ニューヨークタイムズの完全な技術的および財政的サポートを享受しています。 150号以上30,000つ星(1:200)以上です。

https://github.com/mbostock/d

未解決の問題の数が多いということは、開発者が解決できるよりも早くバグを発見していることを意味します。おそらく、開発者はおそらく新しいプロジェクトに移行しており、このライブラリの保守に関心を失っています。

つまり、ライブラリ自体の機能制限に遭遇したことになります。これが発生した場合、2つのオプションがあります。

1.ライブラリの使用を中止して新しいライブラリを選択するか、独自のライブラリを作成します。

残念ながら私はこれを調べましたが、本当に良いangularテーブルライブラリが現在ありません

2.リポジトリをフォークし、ライブラリの内部の仕組みを学び、必要な機能を実装し、プルリクエストを行います。

完全に残念なことではありませんが、UI-Gridng-tableが失敗した場合に役立つ可能性があります。

http://ui-grid.info/

開示:私はui-gridとは関係がなく、それでも良いかどうかについてはまだかなりの部分を囲んでいます

4
Code Whisperer

私たちの状況では、ng-table-dynamicを使用して、カスタム列のセットをデータベースからユーザーのリストにコードレベルでマップする必要があるカスタム列のセットを用意しています。マッピングはコードレベルで手動で行われるため、ng-table-dynamicを使用したフィルタリングと並べ替えを処理する独自の方法が見つかります。

これがコードです

 
 function initialize(){
 this。$ scope.userList = new this.NgTableParams({
 page:1、
 count:10 
}、{
カウント:[]、
合計:this.usersList.length、
 getData:(params)=> {//カスタムソートを処理するかfiltering 
 var results = []; 
 
 
 //ロジックがあればここに追加
 results = this。$ filter( 'filter') (results、this。$ scope.searchKey); 
 
 params.total(results.length); 
 pages = Math.ceil(params.total()/ params.count ()); 
 if(pages> 1){
 results = results.slice((params.page()-1)* params.count()、params.page()* params .count()); 
} 
結果を返す; 
} 
}); 
} 
 

注:宣言された変数の結果を使用しました。これには、テーブルにレンダリングされるデータが含まれます。

また、コントローラでは、カスタム検索を処理する必要があります

ここにコードがあります:

 
 this。$ scope。$ watch( 'searchKey'、(newValue)=> {
 if(typeof newValue!== 'undefined'){
 this。$ scope.userList.reload(); //キーを押すと結果が再レンダリングされる
} 
}); 
 

このコードは、NgTableParamsのgetData関数をトリガーし、カスタムフィルターを構築できるようにします。

注:結果の配列も保持する必要があるため、$ scope変数に格納する必要があります

コードは次のようになります

 
 function foo(){
 Provider( 'Method'、(error、users)=> {
 if(!error){
 this.usersList = users; 
 this。$ scope.userList.reload(); //結果をテーブルにレンダリングします
 this。$ scope。$ apply(); 
} 
}); 
} 
 
0
Kevin Alviola