2013-06-16 11 views
36

W większości przypadków wynikiem <custom-resource>.query() metody jest tablicą, która może być łatwo rozszerzony z kilkoma metodami (logika biznesowa) o następujących (fabrycznych) Kod:

var Data = $resource('http://..'); 
Data.prototype.foo = function() {return ...}; 

ten jest idealny do korzystania z ng-ng/powtarzania klasy, tak jak poniżej:

<tr ng-repeat="item in responseData" ng-class="{warning: item.foo()}">..</tr> 

Moim problemem jest to, że każda odpowiedź lista jest zamknięta w obiekt, który, oprócz aktualnej liście, ma pewne meta- nieruchomości (Sortowanie informacji itp), więc ostateczny obiekt zwrócony jest tak:

{ order_field: "name", items: [{..}, {..},{..}] } 

Teraz, w jaki sposób mogę zrobić to samo, co poprzednio z ng-repeat/NG-klasie?

<tr ng-repeat="item in responseData.items" ng-class="????">..</tr> 

poprzednia metoda nie zadziała jako „foo” metoda jest zdefiniowana na responseData a nie na item obiektu

Czy istnieje jakiś sposób, aby bezpośrednio rozszerzać klasę bazową używany instancji obiektów na liście ?

Dzięki!

Odpowiedz

52

Znalazłem ten problem wcześniej, a rozwiązanie wydaje się być transformResponse, jak mówi John Ledbetter w drugiej odpowiedzi.

Zresztą jeśli trzeba trzymać cały obiekt, a także mając na tablicę w „pozycji” wypełnionych wystąpieniami zasobu, to może być w stanie zrobić to z następującej sztuczki:

Biorąc przykład z Jana odpowiedź i modyfikując go trochę:

angular.module('foo') 

    .factory('Post', ['$resource', function($resource) { 

    var Post = $resource('/api/posts/:id', { id: '@id' }, { 
     query: { 
     method: 'GET', 
     isArray: false, // <- not returning an array 
     transformResponse: function(data, header) { 
      var wrapped = angular.fromJson(data); 
      angular.forEach(wrapped.items, function(item, idx) { 
      wrapped.items[idx] = new Post(item); //<-- replace each item with an instance of the resource object 
      }); 
      return wrapped; 
     } 
     } 
    }); 

    Post.prototype.foo = function() { /* ... */ }; 

    return Post; 
    }]); 
+1

Myślę, że to solidne rozwiązanie. Dla mnie to nie jest idealne, ale najlepsze, jakie widziałem :) –

+0

Dziękuję za tę odpowiedź. –

9

Jeśli używasz skośnych zasobu 1.1.5 (która o ile mogę powiedzieć, faktycznie działa dobrze z kątowym 1.0.7), istnieje opcja transformResponse można określić, kiedy przesłanianie $resource metody:

angular.module('foo') 
    .factory('Post', ['$resource', function($resource) { 

    var Post = $resource('/api/posts/:id', { id: '@id' }, { 
     query: { 
     method: 'GET', 
     isArray: true, 
     transformResponse: function(data, header) { 
      var wrapped = angular.fromJson(data); 
      return wrapped.items; 
     } 
     } 
    }); 

    Post.prototype.foo = function() { /* ... */ }; 

    return Post; 
    }]); 

Jeśli to zrobisz, nie musisz już ręcznie wyciągać elementów z zapakowanej odpowiedzi, a każdy element będzie instancją o numerze Post, która ma dostęp do metody .foo. Możesz po prostu napisać:

<tr ng-repeat="post in posts" ng-class="{warning: post.foo()}">..</tr> 

Wadą tego jest to, że tracisz dostęp do któregokolwiek z zewnętrznych pól w odpowiedzi, które nie są wewnątrz przedmiotów. Wciąż staram się znaleźć sposób na zachowanie tych metadanych.

+0

dziękuję, ale to nie jest to, czego szukam. Ponieważ piszę zarówno frontend CSS, jak i C# -backend, mógłbym po prostu uniknąć zawijania listy w obiekcie, ale chodzi o to, że potrzebuję tych metadanych. – migajek

+1

@migajek Rozumiem, jestem w podobnej sytuacji - chciałbym móc obsługiwać stronicowanie/sortowanie za pomocą mojego API bez konieczności ręcznego "rozpakowywania" wszystkich zasobów. Zainteresuj się, czy są na to dobre odpowiedzi. –

+0

Dodaję metadane, dodając zmienną zamykającą function() { var meta = {}; var Product = $ resource = {tranformResponse: function (data) { meta.prop = data.prop;} } Product._meta = meta; Zwróć produkt; } – ebt

4

to stara sprawa, ale ja po prostu wpadł na ten problem samodzielnie. Rozwiązanie Gargca jest właściwym podejściem, ale jest poprawa. transformResponse akceptuje tablicę, która zostaje przekazana do usługi $http. Zamiast całkowicie zastąpić funkcję transformacji, można dodać swoje przekształcać do wartości domyślnych po prostu dokonać aktualizacji potrzebne:

angular.module('foo') 
    .factory('Post', function ($resource, $http) { 
     var Post = $resource('/api/posts/:id', { id: '@id' }, { 
      query: { 
       method: 'GET', 
       isArray: false, 
       transformResponse: $http.defaults.transformResponse.concat(function(data, header) { 
        angular.forEach(data.items, function(item, idx) { 
         data.items[idx] = new Post(item); 
        }); 
        return data; 
       }) 
      } 
     }); 

     Post.prototype.foo = function() { /* ... */ }; 

     return Post; 
    }); 
0

Można umieścić metadane w nagłówku. Zawsze umieszczam tam dane stronicowania.W ten sposób zapytanie nadal będzie zwracało tablicę, co moim zdaniem jest dobre. Zapytania powinny zwracać tablice danych, a nie pojedyncze dane.