J'essaie de construire une table à l'aide de ngTable, mais avec un filtrage personnalisé différent de celui décrit dans l'exemple de la page ngTable .
Je veux que le filtrage soit en place, mais je ne veux pas que ngTable rende les sélecteurs de filtre. Je veux les rendre moi-même (au-dessus de la table), puis les référencer dans ma méthode "getData ()".
L'exemple cité plus haut n'explique pas le fonctionnement de ces machines. Je ne sais pas exactement ce qui doit être spécifié dans la propriété "filter" de chaque élément "td". Je comprends la syntaxe de base de la fonction de filtre AngularJS $, mais je ne vois pas très bien ce que ngTable fait avec cela. Dans l'exemple ci-dessus, il semble que je ne puisse effectuer que la vérification "égal à", qui ne sélectionnerait que les lignes dont la valeur de colonne associée est égale à la valeur du filtre. Ce n'est pas vraiment ce dont j'ai besoin.
Ma table a plusieurs colonnes. Deux d'entre eux s'appellent "key" et "failed", respectivement string et boolean. Lorsque je rends ces champs de filtre au-dessus de la table, j'ai besoin d'un libellé personnalisé pour le filtre "en échec". Le filtrage de la colonne "clé" doit correspondre à la valeur du filtre avec toute sous-chaîne des valeurs "clé". Par exemple, si j'ai les valeurs de clé "abc", "abac" et "def", une valeur de filtre de "a" aura pour résultat l'affichage des deux premières entrées, et non de l'entrée "def".
Mettre à jour:
À ce propos, j'aimerais pouvoir comprendre comment faire quelque chose comme ceci:
Supposons que j'ai une expression ngRepeat dans mon élément de table comme ceci, en utilisant des filtres angularjs "standard":
"item in $data | customfilter:param | anothercustomfilter:param"
Nous savons que cela ne fonctionne pas tout à fait, car ces filtres ne s'appliqueront qu'à une seule tranche de page obtenue à partir de la méthode "getData ()". Ce que j'aimerais vraiment pouvoir faire dans ma méthode "getData ()", c'est simplement accéder à toute la chaîne de filtres, y compris les expressions de paramètre, et simplement y passer un tableau différent, c'est-à-dire la totalité de la liste de données d'origine, la tranche de page.
En même temps, je devrais être capable de "désactiver" le filtrage que angularjs fait par lui-même, en exécutant cette chaîne de filtres dans son traitement normal.
Cela semble difficile, mais je trouve que l’API actuelle nécessite beaucoup de couplage entre le code HTML et le code javascript. Ce serait bien si le code HTML pouvait spécifier le filtrage souhaité et que le javascript n'utiliserait que la totalité de la chaîne de filtrage, mais l'utiliserait dans la liste de données complète, pas seulement dans la tranche de page.
Mettre à jour:
Voici un extrait pertinent de mon code 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 -->
Voici mon code 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()));
}
});
Notez que j'ai utilisé cette table ngTable en n'utilisant pas la liste "$ data", et en parcourant simplement ma liste "completedQueries". Lorsque cela fonctionnait ainsi, la liste était immédiatement modifiée lorsque je cliquais sur la case à cocher "Afficher uniquement les requêtes ayant échoué" ou saisissait du texte dans le champ de saisie "keysFilter".
Cependant, maintenant que j'utilise la liste "$ data", rien ne se passe lorsque je change un de ces champs. En fait, j'ai même ajouté $ watch-es pour ces deux champs, et aucun d'eux ne se déclenche. Cependant, lorsque j'apporte des modifications à l'un de ces champs, je sais que les données du tableau sont en cours de réévaluation, car deux des colonnes contiennent des données censées représenter une valeur en millis et j'ai un filtre personnalisé sur les colonnes qui traduisent la valeur en une expression anglaise "il y a le temps", comme "il y a 30 secondes" ou "il y a 2 minutes", et chaque fois que je modifie l'un de ces champs de saisie, je vois que les expressions de la table changent, mais cela ne fonctionne toujours pas filtrage approprié.
Si cela compte, voici les $ watch-es que j'ai ajoutés à ma portée. Ceux-ci ne semblent jamais tirer:
$scope.$watch("showOnlyFailed", function() {
$scope.tableParams.reload();
});
$scope.$watch("keysFilter", function() {
$scope.tableParams.reload();
});
Notez que lorsque je les commente, je vois l’erreur suivante après avoir touché ma méthode "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
C'est le bloc de code pertinent:
$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());
});
Mettre à jour:
Voici mon plunkr qui démontre que la modification des champs de filtrage externes ne fonctionne pas. J'ai aussi deux commentaires $ commentés pour essayer de rectifier cela. Lorsque je commente ceux qui entrent, je reçois une erreur dans ng-table, se plaignant d'une portée nulle.
Mettre à jour:
J'ai essayé d'ajouter les paramètres "newvalue, oldvalue" à mes $ watch-es (j'ai mis à jour le plunkr). Maintenant, les modifications apportées aux champs entraînent la mise à jour de la table. Malheureusement, j'ai toujours cette trace de pile à la ligne 411 de ng-table.
Vous n'avez pas besoin des montres ni des filtres personnalisés que vous avez créés. En fait, le filtre "filter" d'angular est assez puissant.
Il vous suffit de créer un objet qui garde la trace de vos valeurs de filtre avec les membres correspondant aux champs de vos éléments. Quelque chose comme ça.
$scope.filter = {
key: undefined,
failed: undefined
}
vous pouvez ensuite le reprendre dans le rappel getData
à l'aide de params.filter()
. J'ai mis à jour votre plunker here _. Vous pouvez également consulter l'exemple ci-dessous:
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>
Il semble que vous rencontriez un problème avec ng-table
lui-même, qui est une bibliothèque tierce qui n'est pas vraiment bien supportée.
Pour preuve, consultez leur page Github, qui compte plus de 200 numéros en suspens et 1 200 étoiles (1: 6):
https://github.com/esvit/ng-table
Comparez cela à une bibliothèque comme D3.js
, qui bénéficie de tout le soutien technique et financier du New York Times. Il a 150 numéros et plus de 30 000 étoiles (1: 200).
https://github.com/mbostock/d3
Un grand nombre de problèmes ouverts signifie que les gens trouvent des bogues plus rapidement que les développeurs ne peuvent les résoudre. Plus que probablement, les développeurs sont probablement passés à de nouveaux projets et ne sont plus intéressés par la maintenance de cette bibliothèque.
En d'autres termes, vous avez rencontré une limitation de fonctionnalité de la bibliothèque elle-même. Lorsque cela se produit, vous avez deux options,
_ {Malheureusement, j'ai examiné cela et il n'y a pas vraiment de bonne bibliothèque de tables angulaires pour le moment} _
Juste pour que ce ne soit pas une déception totale, peut-être que UI-Grid
peut vous aider là où ng-table
a échoué.
Divulgation: je ne suis pas affilié à ui-grid et je ne sais toujours pas si c'est vraiment bon}
Dans notre cas, nous avons utilisé ng-table-dynamic pour créer un ensemble de colonnes personnalisées; ces colonnes personnalisées doivent être mappées sur la liste des utilisateurs de la base de données au niveau du code. Etant donné que le mappage est effectué manuellement au niveau du code, nous trouvons une manière unique de gérer le filtrage et le tri avec ng-table-dynamic.
Voici le code
function initialize () { this. $ scope.userList = new this.NgTableParams ({ page: 1, count: 10 }, { count: [], total: this.usersList.length , getData: (params) => {// gère le tri ou le filtrage personnalisé var results = []; // ajoute une logique ici s'il y en a results = this . $ filter ('filter') (résultats, 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 ()); } renvoyer les résultats; } }); }
Note: Nous avons utilisé une variable déclarée result, où elle contiendra les données à restituer à la table .
De plus, dans le contrôleur, nous devons gérer la recherche personnalisée
voici le code:
this. $ scope. $ watch ('searchKey', (newValue) => { if (type of newValue! == 'undefined') { this. $ scope.userList.reload (); // cause nouvelle restitution du résultat en appuyant sur la touche } });
Ce code déclenchera la fonction getData de NgTableParams, vous permettant de créer votre filtre personnalisé .
Remarque: vous devez également conserver le tableau de résultats, vous devez donc le stocker dans la variable $ scope
Le code ressemblera à ceci
fonction foo () { Fournisseur ('Méthode', (erreur, utilisateurs) => { If (! Erreur) { This.usersList = utilisateurs; This. $ Scope.userList.reload (); // cause le rendu des résultats à la table this. $ scope. $ apply (); } }); }