web-dev-qa-db-fra.com

Angular.js filtre de date personnalisé ui-grid

J'utilise la grille angulaire, ui-grid, située dans ui-grid.info .

J'essaie de créer un filtre personnalisé qui filtrera la grille par date à l'aide de commandes de saisie de date, l'une pour moins de et l'autre pour plus de.

Je semble être capable de mettre les commandes où je les veux en utilisant ceci dans le columnDefs: { field: 'mixedDate', cellFilter: 'date', filterHeaderTemplate: '<div>From <input type="date"> to <input type="date"></div>' }. Je peux également obtenir une sorte de filtrage en définissant le paramètre data-ng-model = "colFilter.term" lorsque vous placez ces éléments dans un champ d'application différent. Le filtrage ne semble même pas faire un égal cependant.

Quelqu'un a-t-il un code qui fonctionne ou qui peut me diriger dans la bonne direction?

Voici quelques tutoriels sur le sujet sur leur propre site, mais je ne sais pas trop comment les manipuler pour répondre à mes besoins ou même si c'est possible.

7
jgerstle

Voulez-vous dire quelque chose comme ça ?  enter image description here

Vous devez d’abord inclure jQuery UI Datepicker

Ensuite, vous créerez également une directive pour cela:

app.directive('datePicker', function(){
    return {
        restrict : "A",
        require: 'ngModel',
        link : function(scope, element, attrs, ngModel){
            $(function(){
                $(element).datepicker({
                     changeMonth: true,
                     changeYear: true,
                     closeText: 'Clear',
                     showButtonPanel: true,
                     onClose: function () {
                        var event = arguments.callee.caller.caller.arguments[0];
                        // If "Clear" gets clicked, then really clear it
                        if ($(event.delegateTarget).hasClass('ui-datepicker-close')) {
                            $(this).val('');
                            scope.$apply(function() {
                               ngModel.$setViewValue(null);
                            });
                        }
                    },
                    onSelect: function(date){
                        scope.$apply(function() {
                           ngModel.$setViewValue(date);
                        });
                    }
               });
            })
        }
    }
})

Dans votre columnDefs, vous devrez également utiliser les filtres client et le modèle d'en-tête de filtre:

filters:[{ condition: checkStart}, {condition:checkEnd}],filterHeaderTemplate: '<div class="ui-grid-filter-container">from : <input style="display:inline; width:30%" class="ui-grid-filter-input" date-picker type="text" ng-model="col.filters[0].term"/> to : <input style="display:inline; width:30%" class="ui-grid-filter-input" date-picker type="text" ng-model="col.filters[1].term"/></div>'

Supposons que vous utilisez momentjs. Les fonctions de filtrage seront comme ceci:

function checkStart(term, value, row, column) {
        term = term.replace(/\\/g,"")
        var now = moment(value);
        if(term) {
            if(moment(term).isAfter(now, 'day')) return false;;
        } 
        return true;
    }

    function checkEnd(term, value, row, column) {
        term = term.replace(/\\/g,"")
        var now = moment(value);
        if(term) {
            if(moment(term).isBefore(now, 'day')) return false;;
        } 
        return true;
    }
4
Qi Tang

Si quelqu'un d'autre cherche une solution à ce problème, j'ai implémenté les filtres FROM et TO personnalisés dans l'en-tête de la grille en utilisant des modaux ui-bootstrap contenant des sélecteurs de date. Voir ce plunker pour plus de détails .

Rétrospectivement, c’est évident, mais l’un des facteurs déterminants dans la recherche de la solution a été de s’assurer que les valeurs de date renseignant la colonne de date dans la grille étaient bien du type Date. Il s'avère que comparer les dates sélectionnées entre les sélecteurs de date et les chaînes ne vous mènera pas très loin.

Remarque: cette solution dépend de lodash pour certaines transformations de données.

var app = angular.module('app', ['ngAnimate', 'ui.grid', 'ui.grid.selection', 'ui.bootstrap']);

app.controller('MainCtrl', ['$scope', '$http', 'uiGridConstants', function ($scope, $http, uiGridConstants) {

  $scope.gridOptions = {
    enableFiltering: true,
    onRegisterApi: function(gridApi){
      $scope.gridApi = gridApi;
    },
    columnDefs: [
      {
        field: 'DATE_TIME',
        displayName: 'Date Time',
        enableFiltering: true,
        enableCellEdit: false,
        filterHeaderTemplate: '<div class="ui-grid-filter-container row"><div ng-repeat="colFilter in col.filters" class="col-md-6 col-md-offset-0 col-sm-6 col-sm-offset-0 col-xs-6 col-xs-offset-0"><div custom-grid-date-filter-header></div></div></div>',
        filters: [
          {
            name: 'From',
            condition: uiGridConstants.filter.GREATER_THAN_OR_EQUAL
          },
          {
            name: 'To',
            condition: uiGridConstants.filter.LESS_THAN_OR_EQUAL
          }
        ],
        cellFilter: 'date:"M/d/yyyy h:mm:ss a"',
        width: '40%'
      },
      {
        field: 'QTY',
        displayName: 'Quantity',
        enableCellEdit: false,
        enableFiltering: false
      },
      {
        field: 'UNIT_COST',
        displayName: 'Unit Cost',
        enableCellEdit: false,
        enableFiltering: false
      },
      {
        field: 'TOTAL_COST',
        displayName: 'Total Cost',
        enableCellEdit: false,
        enableFiltering: false
      }
    ]
  };

  // in plnkr, grab the following data from external file
  // $http.get('grid-data.json')
  //    .success(function(data) {
  //    $scope.gridOptions.data = data;
  
  $scope.gridOptions.data = [
    {
      "DATE_TIME": "2015-10-12T10:46:27.000Z",
      "QTY": 3,
      "UNIT_COST": 0.25,
      "TOTAL_COST": 0.75
    },
    {
      "DATE_TIME": "2015-10-18T06:09:27.000Z",
      "QTY": 4,
      "UNIT_COST": 0.25,
      "TOTAL_COST": 1.00
    },
    {
      "DATE_TIME": "2015-10-05T11:57:27.000Z",
      "QTY": 6,
      "UNIT_COST": 0.55,
      "TOTAL_COST": 0.90
    },
    {
      "DATE_TIME": "2015-10-21T03:42:27.000Z",
      "QTY": 8,
      "UNIT_COST": 0.25,
      "TOTAL_COST": 2.00
    },
    {
      "DATE_TIME": "2015-09-29T18:25:27.000Z",
      "QTY": 3,
      "UNIT_COST": 0.45,
      "TOTAL_COST": 1.35
    },
    {
      "DATE_TIME": "2015-09-19T21:13:27.000Z",
      "QTY": 5,
      "UNIT_COST": 0.25,
      "TOTAL_COST": 1.25
    },
    {
      "DATE_TIME": "2015-08-31T15:46:27.000Z",
      "QTY": 7,
      "UNIT_COST": 0.10,
      "TOTAL_COST": 0.70
    },
    {
      "DATE_TIME": "2015-10-12T10:14:27.000Z",
      "QTY": 2,
      "UNIT_COST": 0.65,
      "TOTAL_COST": 1.30
    }
  ];

  // make sure date values are Date objects
  _.forEach($scope.gridOptions.data, function (val) {
    val.DATE_TIME = new Date(val.DATE_TIME);
  });

}])

.controller('gridDatePickerFilterCtrl', ['$scope', '$timeout', '$uibModal', 'uiGridConstants', function( $scope, $timeout, $uibModal, uiGridConstants) {

  $timeout(function() {
    console.log($scope.col); 
    var field = $scope.col.colDef.name;

    var allDates = _.map($scope.col.grid.appScope.gridOptions.data, function(datum) {
      return datum[field];
    });
      
    var minDate = _.min(allDates);
    var maxDate = _.max(allDates);

    $scope.openDatePicker = function(filter) {
      
      var modalInstance = $uibModal.open({
        templateUrl: 'custom-date-filter.html',
        controller: 'customGridDateFilterModalCtrl as custom',
        size: 'md',
        windowClass: 'custom-date-filter-modal',
        resolve: {
          filterName: [function() {
            return filter.name;
          }],
          minDate: [function() {
            return new Date(minDate);
          }],
          maxDate: [function() {
            return new Date(maxDate);
          }],
        }
      });
  
      modalInstance.result.then(function(selectedDate) {
        
        console.log('date', selectedDate);
        $scope.colFilter.listTerm = [];
        
        console.log(typeof selectedDate);
        console.log(selectedDate instanceof Date);
        
        $scope.colFilter.term = selectedDate;
      });
    };
      
  });
  

}])
.controller('customGridDateFilterModalCtrl', ['$scope', '$rootScope', '$log', '$uibModalInstance', 'filterName', 'minDate', 'maxDate', function($scope, $rootScope, $log, $uibModalInstance, filterName, minDate, maxDate) {
  
    var ctrl = this;

    console.log('filter name', filterName);
    console.log('min date', minDate, 'max date', maxDate);
    
    ctrl.title = 'Select Dates ' + filterName + '...';
    ctrl.minDate = minDate;
    ctrl.maxDate = maxDate;
    ctrl.customDateFilterForm;
  
    ctrl.filterDate = (filterName.indexOf('From') !== -1) ? angular.copy(ctrl.minDate) : angular.copy(ctrl.maxDate);
    
    function setDateToStartOfDay(date) {
      return new Date(date.getFullYear(), date.getMonth(), date.getDate());
    }

    function setDateToEndOfDay(date) {
      return new Date(date.getFullYear(), date.getMonth(), date.getDate(), 23, 59, 59);
    }

    ctrl.filterDateChanged = function () {
      ctrl.filterDate = (filterName.indexOf('From') !== -1) ? setDateToStartOfDay(ctrl.filterDate) : setDateToEndOfDay(ctrl.filterDate);
      $log.log('new filter date', ctrl.filterDate);
    };
    
    ctrl.setFilterDate = function(date) {
      $uibModalInstance.close(date);
    };

    ctrl.cancelDateFilter = function() {
      $uibModalInstance.dismiss();
    };
  
}])

.directive('customGridDateFilterHeader', function() {
  return {
    template: '<button class="btn btn-default date-time-filter-buttons" style="width:90%;padding:inherit;" ng-click="openDatePicker(colFilter)">{{ colFilter.name }}</button><div role="button" class="ui-grid-filter-button-select cancel-custom-date-range-filter-button ng-scope" ng-click="removeFilter(colFilter, $index)" ng-if="!colFilter.disableCancelFilterButton" ng-disabled="colFilter.term === undefined || colFilter.term === null || colFilter.term === \'\'" ng-show="colFilter.term !== undefined &amp;&amp; colFilter.term != null" tabindex="0" aria-hidden="false" aria-disabled="false" style=""><i class="ui-grid-icon-cancel cancel-custom-date-range-filter" ui-grid-one-bind-aria-label="aria.removeFilter" aria-label="Remove Filter">&nbsp;</i></div>',
    controller: 'gridDatePickerFilterCtrl'
  };
})
;
<!DOCTYPE html>
<html ng-app="app">

  <head>
    <script src="https://cdn.jsdelivr.net/lodash/4.6.1/lodash.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular-animate.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/1.3.2/ui-bootstrap.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/1.3.2/ui-bootstrap-tpls.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/angular_material/1.0.7/angular-material.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-grid/3.1.1/ui-grid.min.js"></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-grid/3.1.1/ui-grid.min.css" type="text/css" />
    <link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/angular_material/1.0.7/angular-material.min.css" />
    <link data-require="bootstrap-css@*" data-semver="3.3.6" rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.css" />
    <script src="script.js"></script>
  </head>

  <body> 
    
    <div ng-controller="MainCtrl">
      <div id="grid1" ui-grid="gridOptions" class="grid"></div>
    </div>
    
    <script type="text/ng-template" id="custom-date-filter.html">
    
      <div class="col-md-12 col-md-offset-0 col-sm-12 col-sm-offset-0 col-xs-12 col-xs-offset-0">
  
        <div class="modal-header">
          <p class="modal-title well custom-date-filter-header">
            <span class="custom-date-filter-title-text">
              {{ custom.title }}
            </span>
          </p>
        </div>
  
        <div class="row modal-body custom-date-filter-container-row">
  
          <form name="custom.customDateFilterForm"
                ng-submit="custom.setFilterDate(custom.filterDate)"
                no-validation>

            <div class="row custom-filter-date-input-row">
            
              <div class="well col-md-8 col-md-offset-2 col-sm-8 col-sm-offset-2 col-xs-10 col-xs-offset-1 custom-date-filter-input">
              
                <uib-datepicker ng-model="custom.filterDate" 
                    min-date="custom.minDate" 
                    max-date="custom.maxDate"
                    ng-change="custom.filterDateChanged()"
                    class="well well-sm">
                </uib-datepicker>

              </div>

            </div>

            <div class="row modal-footer custom-date-filter-submit-buttons-row">

              <div class="custom-date-filter-submit-buttons-div col-lg-8 col-lg-offset-2 col-md-8 col-md-offset-2 col-sm-10 col-sm-offset-1 col-xs-10 col-xs-offset-1">

                <button class="btn btn-success btn-lg custom-date-filter-submit-button"
                        type="submit">
                  Apply
                </button>

                <button type="button"
                        class="btn btn-warning btn-lg custom-date-filter-cancel-button"
                        ng-click="custom.cancelDateFilter()">
                  Cancel
                </button>

              </div>

            </div>

          </form>
  
        </div>
  
      </div>
    
    </script>
  </body>

</html>
3
Bennett Adams

J'utilise angular-ui-grid 3.1.1 et angular-ui-bootstrap 1.3.2.

Ma solution est basée sur l'aide du filtre ui-grid et les commentaires de Munna S/Bennett Adams. J'ai obtenu une solution avec moins de code.

Il fonctionne avec deux filtres et un modèle personnalisé ('ui-grid/custom-ui-grid-filter').

  { field: 'DATE_TIME', name: 'Date Time', cellTooltip: true,
    cellFilter: 'date:\'yyyy-MM-dd\'',
    cellTemplate: 'ui-grid/date-cell',
    filterHeaderTemplate: 'ui-grid/custom-ui-grid-filter',
    width: '40%',
    filters: [
        {
          condition: function(term, value, row, column){
                if (!term) return true;
                var valueDate = new Date(value);
                return valueDate >= term;
            },
          placeholder: 'Greater than or equal'
        },
        {
          condition: function(term, value, row, column){
                if (!term) return true;
                var valueDate = new Date(value);
                return valueDate <= term;
            },
          placeholder: 'Less than or equal'
        }
    ],
    headerCellClass: $scope.highlightFilteredHeader }

N'oubliez pas que dans la fonction condition, le terme provient du filtre DatePicker et est une date. En outre, value est une chaîne au format "aaaa-MM-jj" dans mon exemple.

Voici mon Plunkr J'espère que cela vous aidera et si vous avez des améliorations, merci de me le faire savoir.

2
Aquiles

je l'ai fait en utilisant une méthode javascript personnalisée

condition: function(term, value){
    if (!term) return true;
    var valueDate = new Date(value);
    var replaced = term.replace(/\\/g,'');
    var termDate = new Date(replaced);
    return valueDate < termDate;
},
placeholder: 'less than'
1
Munna S