2016-07-17 13 views
5

Używam ostatnio dyrektywy ngTableDynamic i działa doskonale, gdy dokładnie wiem, jakich kolumn powinna oczekiwać moja tabela. Występują jednak problemy, gdy moja tabela jest prawdziwie dynamiczna i nie wiem z góry liczby lub rodzaju kolumn, których można się spodziewać.Dodawanie kolumn do tabeli dynamicznej na podstawie wyników obietnicy

Na szczycie mojego kontrolera Oświadczam kolumny znam będzie obecna w każdej tabeli:

$scope.columns = [ 
    { title: 'ID', field: 'id', visible: true, required: true }, 
    { title: 'Email', field: 'email', visible: true, required: true } 
]; 

I wtedy zrobić asynchronicznego połączenia z usługą, która zwraca wyniki. Na podstawie tych wyników wciskam jakiekolwiek dodatkowe obiekty kolumn do $scope.columns:

var getResults = function() { 
    var defer = $q.defer(); 
    reportService.getReportResults({ 
    report: $scope.id, 
    version: $scope.version 
    }).$promise.then(function(data) { 
    $scope.data = data.results; 
    _.each($scope.data[0], function(value, key) { 
     if (key !== 'id' && key !== 'email') { 
     $scope.columns.push({ 
      title: _str.capitalize(key), 
      field: key, 
      visible: true, 
      required: false 
     }); 
     } 
    }); 
    defer.resolve($scope.data); 
    }); 
    return defer.promise; 
}; 

Jednak kolumny popychany wewnątrz _.each nie wprowadzać go do mojego stolika, kiedy go zobaczyć w przeglądarce. Jeśli mogę wymienić moje wezwanie asynchroniczny z twardego kodowane mock na przykładzie zestawu danych jednak, kolumny są dodawane i wszystko działa zgodnie z oczekiwaniami:

var getResults = function() { 
    var defer = $q.defer(); 
    $scope.data = [{"id":"1","email":"[email protected]",,"create_date":"2013-09-03T09:00:00.000Z"},{"id":"2","email":"[email protected]","create_date":"2013-09-03T11:10:00.000Z"}]; 
    _.each($scope.data[0], function(value, key) { 
    if (key !== 'id' && key !== 'email') { 
     $scope.columns.push({ 
     title: _str.capitalize(key), 
     field: key, 
     visible: true, 
     required: false 
     }); 
    } 
    }); 
    defer.resolve($scope.data); 
    return defer.promise; 
}; 

Dalej w moim kontroler mój kod startowych wzywa

getResults().then(function() { 
    $scope.tableParams.reload(); 
}); 

$scope.tableParams = new ngTableParams({... 

Moje założenie jest takie, że jak tylko obietnica zostanie rozwiązana, $scope.tableParams.reload(); jest wywoływana przed zaktualizowaniem $scope.columns.

+1

co dzieje się z zakodowanego na stałe wersji modelowej jeśli przeniesiesz że 'getresults(). Następnie (...' wywołanie po utworzeniu '$ scope.tableParams'? – Will

+1

Cześć, nie jestem zbyt biegły w Angular, ale czy mógłbyś mi powiedzieć, co to jest "$ Promise"? 'version: $ scope.version }). $ Promise' Nigdy wcześniej nie widziałem czegoś podobnego. –

+1

@Mridul https://docs.angularjs.org/api/ngResource/service/$resource, znajdź $ promise –

Odpowiedz

2

Na podstawie demo z dokumentacji wystarczyło zrobić przykład z obietnicami. Po prostu wydaje się, że musisz utworzyć nowy obiekt tableParams i cols po otrzymaniu odpowiedzi od obietnicy. Dodanie wierszy do istniejących kolorów może nie spowodować wyzwolenia obserwatora.

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

 
angular.module('app').controller('Demo', function($scope, NgTableParams, dataService) { 
 
    $scope.cols = [{ 
 
    title: 'ID', 
 
    field: 'id', 
 
    visible: true 
 
    }, { 
 
    title: 'Email', 
 
    field: 'email', 
 
    visible: true 
 
    }, { 
 
    title: 'Create Date', 
 
    field: 'create_date', 
 
    visible: true 
 
    }]; 
 
    
 
    dataService 
 
    .getData() 
 
    .then(function (response) { 
 
     $scope.tableParams = new NgTableParams({}, { 
 
     dataset: response.results 
 
     }); 
 
     $scope.cols = $scope.cols.concat(response.cols); 
 
    }); 
 
}); 
 

 
angular.module('app').factory('dataService', function($timeout) { 
 
    return { 
 
    getData: function() { 
 
     return $timeout(function() { 
 
     var n = Math.round(Math.random() * 50) + 5; 
 
     var results = []; 
 

 
     for (var i = 0; i < n; i++) { 
 
      results.push({ 
 
      id: Math.random(), 
 
      email: 'ex' + Math.random() + '@example.com', 
 
      create_date: new Date(), 
 
      x: Math.round(Math.random() * 10), 
 
      y: Math.round(Math.random() * 25) 
 
      }); 
 
     } 
 

 
     return { 
 
      results: results, 
 
      cols: [ 
 
      { 
 
       title: 'X', 
 
       field: 'x', 
 
       visible: true 
 
      }, 
 
      { 
 
       title: 'Y', 
 
       field: 'y', 
 
       visible: true 
 
      } 
 
      ] 
 
     }; 
 
     }, 500); 
 
    } 
 
    }; 
 
});
<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.2/angular.js"></script> 
 
<link rel="stylesheet" href="https://rawgit.com/esvit/ng-table/master/dist/ng-table.min.css"> 
 
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css"> 
 
<script src="https://rawgit.com/esvit/ng-table/master/dist/ng-table.min.js"></script> 
 

 
<div ng-app="app" ng-controller="Demo"> 
 
    <table ng-table-dynamic="tableParams with cols" class="table table-condensed table-bordered table-striped"> 
 
    <tr ng-repeat="row in $data"> 
 
     <td ng-repeat="col in $columns">{{row[col.field]}}</td> 
 
    </tr> 
 
    </table> 
 
</div>

1

Powodem jest to, że stosuje się dane z zakresu $ asynchronicznie (w obietnicy następnie blok), dzięki czemu są poza kątowego strawić cyklu, a tabela nie będzie zaktualizować.

Nie dzieje się to w twojej sztuczce, ponieważ synchronizujesz plik $ scope.data. (A more detailed explanation can be found here)

Aby to naprawić, powinieneś poinformować kątowo, że dokonałeś pewnych zmian w zakresie za pomocą $ scope.$ Strawienia()

widzę jakieś inne problemy z kodem, który postaram się zająć

  • złe wykorzystanie obietnic (czytaj: unikać „defer” kiedy tylko możesz)
  • nie funkcjonalne zbliżać
  • trochę zamieszania o obietnicach/kątowych w ogólnym

Dość gadania, to jak bym napisać tę samą funkcję:

var getResults = function() { 

    // fetch data 
    return reportService.getReportResults({ 
      report: $scope.id, 
      version: $scope.version 
     }) 
     .then(function(data) { 

      // assign the values 
      $scope.data = data.results 

      // notify angular to recheck his array 
      $scope.$digest() 

      // consider using a functional approach to have a cleaner code 
      _($scope.data) 
       .first() 
       .keys() 
       .filter(key => (key !== 'id' && key !== 'email')) 
       .each(key => { 
        $scope.columns.push({ 
         title: _str.capitalize(key), 
         field: key, 
         visible: true, 
         required: false 
        }) 
       }) 
       .value() 

      return $scope.data 
     }) 
} 
0

Spróbuj go jako

var getResults = function() { 
    var defer = $q.defer(); 
    reportService.getReportResults({ 
    report: $scope.id, 
    version: $scope.version 
    }).$promise.then(defer.resolve); 
    return defer.promise; 
}; 


getResults().then(function(_data) { 
$scope.data = _data; 
_.each($scope.data, function(value, key) { 
     if (key !== 'id' && key !== 'email') { 
     $scope.columns.push({ 
      title: _str.capitalize(key), 
      field: key, 
      visible: true, 
      required: false 
     }); 
     } 
    }); 

}); 

lub bezpośrednio w kontrolerze jako

reportService.getReportResults({ 
    report: $scope.id, 
    version: $scope.version 
    }).then(function(_data) { 
    $scope.data = _data; 
    _.each($scope.data, function(value, key) { 
      if (key !== 'id' && key !== 'email') { 
      $scope.columns.push({ 
       title: _str.capitalize(key), 
       field: key, 
       visible: true, 
       required: false 
      }); 
      } 
     }); 

    }); 
Powiązane problemy