Как назначить класс для отчета не для нечетных, четных строк, а при изменении столбца даты?

У меня очень простой отчет в AngularJS:

<div class="gridHeader">
   <div>User</div>
   <div>Date</div>
   <div>Count</div>
</div>
<div class="gridBody"
   <div class="gridRow" ng-repeat="row in rps.reports">
      <div>{{row.user}}</div>
      <div>{{row.date}}</div>
      <div>{{row.count}}</div>
   </div>
</div>

Отчет работает, но при изменении даты его трудно заметить.

Есть ли способ, которым я мог бы назначить класс для строки сетки, чтобы одна строка сетки дат имела один класс, а следующая дата, когда в строке решетки есть другой класс. Я думаю, что это уже доступно для нечетных и четных строк с Angular, но здесь мне нужно, чтобы он работал при каждом изменении даты.

Ответы

Ответ 1

Я создал очень простое и рабочее решение для этого, используя angular-filter, вам нужно добавить динамический класс на gridRow.

jsfiddle

HTML

<div ng-repeat="row in rps.reports" 
    class="gridRow {{row.date | filterDate}}">

Стили

.even {
  background-color: green;
  color: #fff;
}
.odd {
  background-color: red;
  color: #000;
}

Angular -filter

myApp.filter('filterDate', function() {
  var lastDate,
    count = 0,
    calssName = 'even';
  return function(date) {
    var newDate = new Date(date).toDateString();
    !lastDate && (lastDate = newDate);
    if (newDate != lastDate) {
      if (calssName == 'even') {
        calssName = 'odd';
      } else {
        calssName = 'even';
      }
    }
    lastDate = newDate;
    return calssName;
  }
});

Ответ 2

Я сделал другое решение (PLUNKER), где вся работа находится внутри контроллера. Может быть, это немного больше кода, но вы получите большую производительность, если у вас есть тысячи записей, потому что вы избежите грязной проверки ng-class.
Кроме того, если ваш отчет статичен и он не будет иметь никаких изменений, вы можете отключить привязку данных...

CONTROLLER

vm.reports = addReportCssClases();

function addReportCssClases() {
    var reportsData = [...]; 
    var classes = ['dateOdd', 'dateEven'];
    var index = 0; 

    reportsData[0].cssClass = classes[index];

    for (var i = 1; i < reportsData.length; i++) {
      var row = reportsData[i]; 
      index = (row.date !== reportsData[i-1].date) ? (1 - index) : index;
      row.cssClass = classes[index] ;
    }

    return reportsData;
}

HTML

<div ng-repeat="row in vm.reports track by $index" class="gridRow {{::row.cssClass}}">
    <div>{{::row.user}}</div>
    <div>{{::row.date}}</div>
    <div>{{::row.count}}</div>
</div>

Ответ 3

Вы можете использовать ng-class с функцией, определенной в вашем контроллере. Например:

var currentColor = "color1";

$scope.getClass = function(index)
{
  if (index !== 0 && $scope.data[index].date !== $scope.data[index - 1].date)
  {
    currentColor = currentColor == "color1" ? "color2" : "color1";
  }

  return currentColor;
}

И в вашем шаблоне:

<div class="gridRow" ng-repeat="(i, d) in data" data-ng-class="getClass(i)">

Смотрите плункер: http://plnkr.co/edit/PPPJRJJ1jHuJOgwf9lNK

Ответ 4

Это можно сделать с помощью одной строки, учитывая, что все даты на самом деле совпадают с тем же форматом, а не с датой даты

<div class="gridHeader">
   <div>User</div>
   <div>Date</div>
   <div>Count</div>
</div>
<div class="gridBody">
   <div  ng-repeat="row in rps.reports" class="gridRow"  ng-class="{'backblue':$index>0 && row.date!=rps.reports[$index-1].date}">
      <div>{{row.user}}</div>
      <div>{{row.date}}</div>
      <div>{{row.count}}</div>
   </div>
</div>

ваш класс gridRow должен содержать фоновый цвет

.gridRow{
  //other styles
  background-color:red;
}

а класс backblue должен иметь только фоновый цвет

.backblue{
   background-color:blue !important;
}

ВАЖНО Это будет работать, только если поле даты является только датой и не имеет времени. Если в любом случае у вас есть время, вам придется конвертировать каждое время и дату

Ответ 5

Измененная версия ответа @ssougnez, сохраняя текущую дату также в дополнение к цвету:

if(!(currentDate && currentDate === data.date)){
  currentColor = currentColor == "color1" ? "color2" : "color1";
  currentDate = data.date;
}

Plunker: http://plnkr.co/edit/o3YVBB

Это может иметь меньшее влияние на производительность, чем его версия.

Ответ 6

var app = angular.module('sample', []);

app.controller('SampleController', function($scope) 
{
 $scope.data = [
    {
      user: "A",
      date: "3/2/2017"
    },
    {
      user: "B",
      date: "3/4/2017"
      
    },
    {
      user: "C",
      date: "4/3/2017"
    },
      {
      user: "D",
      date: "4/3/2017"
    },
      {
      user: "E",
      date: "4/3/2017"
    },
      {
      user: "F",
      date: "4/2/2017"
    }  
  ];
  
});
.same{
background-color:#ddd;

}

.differ{
background-color:yellow;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html ng-app="sample">
<head>

</head>
<body>


<div ng-controller="SampleController">
<table id="myTable">
<thead>
<tr>
   <th>User</th>
   <th>Date</th>
 </tr>
</thead>
<tbody>
   <tr ng-repeat="row in data">
      <td>{{row.user}}</td>
      <td class="same" ng-if="data[$index+1].date==row.date || data[$index-1].date==row.date">{{row.date}}</td>
      <td class="differ" ng-if="data[$index+1].date!=row.date && data[$index-1].date!=row.date">{{row.date}}</td>
   </tr>
</tbody>
</table>
</div>
</body>
</html>

Ответ 7

Вы можете добавить класс с выражением, используя директиву ngClass в представлении:

(function() {

  'use strict';

  angular.module('app', []);

})();

(function() {

  'use strict';

  angular.module('app').controller('MainController', MainController);

  MainController.$inject = ['$scope'];

  function MainController($scope) {

    var date = new Date();

    $scope.rps = {
      reports: [{
          user: 'User A',
          date: date.setDate(date.getDate() + 1),
          count: 5
        },
        {
          user: 'User B',
          date: date.setDate(date.getDate() + 2),
          count: 10
        },
        {
          user: 'User C',
          date: date.setDate(date.getDate()),
          count: 8
        },
        {
          user: 'User D',
          date: date.setDate(date.getDate() + 2),
          count: 6
        },
        {
          user: 'User E',
          date: date.setDate(date.getDate()),
          count: 20
        },
        {
          user: 'User F',
          date: date.setDate(date.getDate() + 3),
          count: 6
        }
      ]
    };

  }

})();
.gridHeader,
.gridRow {
  display: table-row;
}

.gridHeader>div,
.gridRow>div {
  display: table-cell;
  padding: 5px 10px;
}

.className {
  background: #ff0000;
  color: #fff;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.3/angular.min.js"></script>

<div ng-app="app" ng-controller="MainController as MainCtrl">

  <div class="gridHeader">
    <div>User</div>
    <div>Date</div>
    <div>Count</div>
  </div>
  <div class="gridBody">
    <div class="gridRow" ng-repeat="row in ::rps.reports track by $index" ng-class="::{'className': $index === 0 || $index > 0 && rps.reports[$index - 1].date !== row.date}">
      <div>{{::row.user}}</div>
      <div>{{::row.date | date: 'dd-MM-yyyy'}}</div>
      <div>{{::row.count}}</div>
    </div>
  </div>

</div>