2013-04-05 12 views
9

Ho un $resource la cui API restituirà sempre alcuni dati che devono essere ripuliti prima di passare al livello di presentazione. Nello specifico, è .NET che restituisce oggetti Date nel delizioso formato '/Date(...)/'.

Non voglio dover scrivere una richiamata ogni volta che chiamo .query() o .get(). Esiste un modo per estendere la risorsa con un callback che viene richiamato sui metodi REST che aggiornano le proprietà dell'istanza o aggiungendo una sorta di $watch che viene generato quando la proprietà della data cambia? Fondamentalmente qualcosa che accadrà per ogni istanza di questo $resource.

angular.module('myAppServices', ['ngResource']) 
    .factory('Participant', ['$resource', function ($resource) { 
     var res = $resource('api/url/participants/:id', { id: '@id' }); 

     // This obviously doesn't work, but something kinda like this? 
     res.prototype.$watch(this.FieldName, function(newVal, oldVal) { 
      if (needsCleaning(newVal.fieldName) { 
       this.FieldName = cleanupField(newVal); 
      } 
     }; 
    }); 
+0

puoi provare questo. 'var partecipante = $ risorsa ('api/url/partecipanti /: id', {id: '@id'}); var commonCallback = function() { \t // all'interno di questo callback, il partecipante è il modello popolato, \t // è possibile utilizzare l'oggetto partecipante per eseguire la logica di formattazione. \t // Quindi, se si desidera salvare l'oggetto partecipante fare \t //participant.$save(); Si prega di non i nomi dei metodi con prefisso $ che diventano disponibili per le istanze delle risorse. } res.query (commonCallback) o res.get ({..}, commonCallback) ' – rajkamal

risposta

12

Ah-ha, ho trovato un modo per aggirarlo e lo lascerò qui. Nella versione 1.1.2 hanno aggiunto il supporto per il passaggio di tutte le opzioni $http.config a $resource. Naturalmente, il CDN che sto usando non ha una versione abbastanza recente di angular-resource.js, ma il cambio di CDN lo ha risolto.

Ho appena utilizzato l'opzione transformResponse per modificare i dati al loro rientro.

angular.module('myAppServices', ['ngResource']) 
    .factory('Participant', ['$resource', '$http', function ($resource, $http) { 
     var res = $resource('api/url/participants/:id', { id: '@id' }, { 
     save: { 
      method: 'POST', 
      transformResponse: $http.defaults.transformResponse.concat([ 
       function (data, headersGetter) { 
        data.FieldName = yourDateParsingFunction(data.FieldName); 

        return data; 
       } 
      ]) 
     } 
    }); 

sto solo aggiungendo il mio trasformatore a $httpProvider 's transformResponse, che farà tutto il deserializzazione, ecc

+1

Grazie , Mi piace la parte '$ http.defaults.transformResponse.concat'. – jvannistelrooy

+0

Nota: non è possibile utilizzare la richiesta AJAX all'interno di 'transformResponse' per modificare i campi dell'oggetto' dati' – MyTitle

+0

Ho dovuto aggiungere un'istruzione return alla fine della funzione factory per farlo funzionare. – rodowi

8

Un modo semplice per farlo è quello di sovrascrivere le esistenti $resource metodi che vuoi fare post-processing su con il vostro. Vedi il codice e i commenti sotto per un esempio.

angular.module('myAppServices', ['ngResource']) 
    .factory('Participant', ['$resource', function ($resource) { 
     var res = $resource('api/url/participants/:id', { id: '@id' }, { 
      // create aliases for query and get to be used later 
      _query: { method: 'GET', isArray: true }, 
      _get: { method: 'GET' } 
     }); 

     // redefine the query method 
     res.query = function() { 
      // call the original query method via the _query alias, chaining $then to facilitate 
      // processing the data 
      res._query.apply(null, arguments).$then(function(res) { 
       var data = res.data; 
       // do any processing you need to do with data here 
       return data; 
      }); 
     }; 

     // redefine the method 
     res.get = function() { 
      // call the original get method via the _get alias, chaining $then to facilitate 
      // processing the data 
      res._get.apply(null, arguments).$then(function(res) { 
       var data = res.data; 
       // do any processing you need to do with data here 
       return data; 
      }); 
     }; 

     return res; 
    }); 

devi usare allo stesso modo si sta attualmente utilizzando Participant nel codice, tramite Participant.query() o Participant.get(). I dati restituiti nel gestore $ incatenato verranno utilizzati per risolvere la promessa restituita da $resource.

+0

Grazie per la risposta. Non sono sicuro al 100%, ma penso che 'transformResponse' potrebbe essere la strada più facile da percorrere. – c0bra

+1

@ c0bra, la via di Intelekshual è utile quando è necessario accedere a variabili che non sono accessibili in 'transformResponse' – jvannistelrooy

+0

Un altro vantaggio di questa soluzione è che possiamo riutilizzare i metodi predefiniti da $ risorse per creare i nostri metodi personalizzati e quindi trasformare facilmente le risposte –

0

Il modo in cui ho fatto è stato con l'aggiunta di un servizio per il modulo:

angular.module('keeniolab', ['ngResource']). 
factory('KeenIO',function ($resource) { 
    // factory implementation 
}).service('KeenModel', function (KeenIO) { 
    var KeenSession = function() { 
     this.data = {}; 
    }; 

    KeenSession.prototype.fetch = function (query) { 
     var self = this; 

     KeenIO.get(query, function (result) { 
      self.data = result; 
     }); 
    }; 

    return new KeenSession(); 
}); 

Ora si può semplicemente monitorare la collezione:

$scope.$watchCollection(function() { 
    return KeenModel.data; 
}, 
function (value) { 
    // code here 
}); 

Keen.IO Resource Factory with Service Model

Problemi correlati