Angular-DataTables: повышение производительности за счет рендеринга с помощью Promise + угловое связывание + индекс строки + groupBy - PullRequest
0 голосов
/ 23 сентября 2018

Я использую эту библиотеку: http://l -lin.github.io / angular-datatables

Все хорошо - я отрисовал таблицу Angular way - пока данные не будутдостаточно большой, чтобы снизить производительность (только 1000+ строк).

Решение состоит в том, чтобы выполнить рендеринг с помощью ajax или обещания, как предлагается здесь: angular-datatables не работает deferRender

Итак, за последние три дня я застрял в том, как преобразовать приведенные ниже коды из углового способа в обещание

УГЛОВОЙ ПУТЬ

view.html

<table datatable="ng" dt-options="dtOptions" class="table table-striped table-bordered">
                                <thead>
                                    <tr>
                                      <th>No</th>
                                        <th>Issue</th>
                                        <th>Meeting No.</th>
                                          <th>Department/Unit</th>
                                   </tr>
                                </thead>
                                <tbody>
                                    <tr ng-repeat="(key, value) in issueList | groupBy : 'IssueId' | reverse track by $index">
                                      <td ng-class="{read : value[0].AnswerStatus == 1}">{{$index+1}}</td>
                                        <td>{{value[0].Issue}}</td>
                                        <td>{{value[0].MeetingNo}}</td>
                                        <td>
                                          <table class="table table-striped table-bordered" cellspacing="0" width="100%">
                                            <tbody>
                                              <tr ng-repeat="x in value">
                                              <td width="80%">{{x.Department}}/{{x.Unit}}</td>
                                            <td>  <a class="btn btn-default waves-effect m-b-5" ng-click="sendDetail(x.IssueId,x.UnitId)"><i class="fa fa-folder-open"></i> Show </a></td>
                                            </tr>
                                            </tbody>
                                          </table>
                                          </td>

                                    </tr>

                    </tbody>
                            </table>

view.js

$scope.dtOptions = 
DTOptionsBuilder.newOptions() 
.withOption('stateSave', true)
.withOption('stateDuration', -1)
.withOption('deferRender', true);

$http({
method: 'GET',
url: 'http://issue.json'})
.then(function(response) {
    $scope.issueList = response.data;
  });

issue.json

[{
    "IssueId": "1",
    "MeetingNo": "1",
    "Issue": "Issue title 1",
    "Content": "Content 1",
    "AnswerStatus": null,
    "UnitId": 1,
    "Unit": "Unit 1",
    "DepartmentId": 1,
    "Department": "Department 1"
}, {
    "IssueId": "2",
    "MeetingNo": "1",
    "Issue": "Issue title 2",
    "Content": "Content 2",
    "AnswerStatus": null,
    "UnitId": 5,
    "Unit": "Unit 5",
    "DepartmentId": 1,
    "Department": "Department 1"
}, {
    "IssueId": "2",
    "MeetingNo": "1",
    "Issue": "Issue title 2",
    "Content": "Content 2",
    "AnswerStatus": 1,
    "UnitId": 6,
    "Unit": "Unit 6",
    "DepartmentId": 1,
    "Department": "Department 1"

}]

Ниже кодамоя половина превращения

ПУТЬ ОБЕЩАНИЯ

view.html

<table datatable="" dt-options="dtOptions" dt-columns="dtColumns" class="table table-striped table-bordered">

                            </table>

view.js

$scope.dtOptions = 
    DTOptionsBuilder.fromFnPromise(function() {
        var defer = $q.defer();
            $http({
          method: 'GET',
          url: 'http://issue.json'
      }).then(function(result) {
            defer.resolve(result.data);
        });
        return defer.promise;
    })    
    .withOption('stateSave', true)
    .withOption('stateDuration', -1)
    .withOption('deferRender', true); //the very reason to use promise for performance booth

$scope.dtColumns = [
DTColumnBuilder.newColumn(null).withTitle('No')
        .renderWith(function(data, type, full, meta) {
            return (meta.row+1);
        }),
 DTColumnBuilder.newColumn('Issue').withTitle('Issue'),
 DTColumnBuilder.newColumn('MeetingNo').withTitle('Meeting No.'),
 DTColumnBuilder.newColumn('Department').withTitle('Department/Unit'), 
 ];

Как видите, в первом столбце отсутствует стиль, необходимый для AnswerStatus == 1, а в последнем столбце отсутствует объединенное значение Department + '/' + Unit и кнопка для перехода кдругая страница.

Также обратите внимание, что угловой способ использует groupBy, что еще больше осложняет мои проблемы: (

Пожалуйста, помогите.Спасибо за ваше время.

ОБНОВЛЕНИЕ:

На самом деле, я также рассматриваю альтернативное решение, но все еще сталкиваюсь с дорожным блоком.Я рассматриваю рефакторинг JSON с этим:

   Array.prototype.groupBy = function(prop) {
    return this.reduce(function(groups, item) {
      const val = item[prop]
      groups[val] = groups[val] || []
      groups[val].push(item)
      return groups
    }, {})
  }

 $scope.dtOptions = 
DTOptionsBuilder

.fromFnPromise(function() {
    var defer = $q.defer();
        $http({
      method: 'GET',
      url: 'http://issue.json'
  }).then(function(result) {

        var d = result.data.groupBy('IssueId');
        var arr = Object.values(d);
        console.log(arr);
        defer.resolve(arr);
    });
    return defer.promise;
})
.withOption('stateSave', true)
.withOption('stateDuration', -1)
.withOption('deferRender', true);

, что приводит к новому массиву пронумерованных массивов, как это (console.log (arr)):

    [
[{
        "IssueId": "1",
        "MeetingNo": "1",
        "Issue": "Issue title 1",
        "Content": "Content 1",
        "AnswerStatus": null,
        "UnitId": 1,
        "Unit": "Unit 1",
        "DepartmentId": 1,
        "Department": "Department 1"
    }], 
[{
        "IssueId": "2",
        "MeetingNo": "1",
        "Issue": "Issue title 2",
        "Content": "Content 2",
        "AnswerStatus": null,
        "UnitId": 5,
        "Unit": "Unit 5",
        "DepartmentId": 1,
        "Department": "Department 1"
    }, {
        "IssueId": "2",
        "MeetingNo": "1",
        "Issue": "Issue title 2",
        "Content": "Content 2",
        "AnswerStatus": 1,
        "UnitId": 6,
        "Unit": "Unit 6",
        "DepartmentId": 1,
        "Department": "Department 1"

    }]
]

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

1 Ответ

0 голосов
/ 23 сентября 2018

Ну, планкр с оригинальной версией здесь http://plnkr.co/edit/Q2ob8gynNTXXId9pxnzz?p=preview

Вот как вы можете реорганизовать JSON так, чтобы он был сгруппирован

$scope.dtOptions = 
  DTOptionsBuilder.fromFnPromise(function() {  
    var defer = $q.defer();
    $http({
      method: 'GET',
      url: 'issues.json'
    }).then(function(result) {
      var data = [];
      result.data.forEach(function(i) {
        var item = data.find(item => item.IssueId == i.IssueId)
        if (item) {
          item.childs.push(i)
        } else {
        data.push({ 
          IssueId: i.IssueId, 
          Issue: i.Issue,
          MeetingNo: i.MeetingNo,      
          childs: [i] 
        })
      }
    }) 
    defer.resolve(data);
  })
  return defer.promise;
})    

Вот как вы можете настроитьстолбцы

$scope.dtColumns = [
  DTColumnBuilder.newColumn(null).withTitle('No')
    .withOption('createdCell', function(cell, cellData, rowData, rowIndex, colIndex) {
      if (rowData.AnswerStatus == 1) $(cell).addClass('read')
    })  
    .renderWith(function(data, type, full, meta) {
      return (meta.row+1);
    }),

  DTColumnBuilder.newColumn('Issue').withTitle('Issue'),
  DTColumnBuilder.newColumn('MeetingNo').withTitle('Meeting No.'),

  DTColumnBuilder.newColumn(null)
    .withTitle('Department/Unit') 
    .renderWith(function(data, type, row, meta) {
       var html = '<table><tbody>';
       row.childs.forEach(function(child) {
         html += '<tr><td>'+child.Department+'/'+child.Unit+'</td></tr>'
         html += '<tr><td><button ng-click="buttonClick()">click</button></td></tr>'
       }) 
       html += '</tbody></table>'
       return html
    })
    .withOption('createdCell', function(cell, cellData, rowData, rowIndex, colIndex) {    
       $compile(cell)($scope);  
    })
]

Просто используйте createdCell для публикации столбцов процесса.Используйте $compile, чтобы заставить работать другие угловые директивы.У вас есть некоторые проблемы, о которых вы не задумывались в исходном коде, например, какой AnswerStatus выбрать.

http://plnkr.co/edit/izRyvvZr4Zo7ioxiOmEI?p=preview

...