2013-03-08 6 views
6

ich eine Ressource, die aus einer Abfrage ein Array zurückgibt, etwa so:Methoden zu einer Sammlung von einer Winkelressourcenabfrage zurück hinzufügen

.factory('Books', function($resource){ 
    var Books = $resource('/authors/:authorId/books'); 
    return Books; 
}) 

Ist es möglich Prototyp Methoden hinzufügen, um das Array von dieser Abfrage zurückgegeben ? (Hinweis, nicht zu array.prototype).

Zum Beispiel möchte ich Methoden wie hasBookWithTitle(title) der Sammlung hinzufügen.

+0

Sehen Sie, ob dies [$ Ressourcenbeziehungen in Angular.js] (http://stackoverflow.com/questions/9981090/resource-relations-in-angular-js) hilft. – Stewie

Antwort

4

Dies ist wahrscheinlich ein guter Fall, um einen benutzerdefinierten Dienst zu erstellen, der die Ressource erweitert und Hilfsmethoden hinzufügt, anstatt den zurückgegebenen Werten Methoden aus dem Standardressourcendienst hinzuzufügen.

var myModule = angular.module('myModule', []); 
myModule.factory('Book', function() { 
    var service = $resource('/authors/:authorId/books'); 
    service.hasBookWithTitle = function(books, title){ 
     //blah blah return true false etc. 
    } 
    return service; 
}); 

dann

books = Book.list(function(){ 
    //check in the on complete method 
    var hasBook = Book.hasBookWithTitle(books, 'someTitle'); 
}) 
5

Der Vorschlag von ricick ist gut, aber wenn man eine Methode auf dem Array haben wollen, um tatsächlich die zurückgibt, werden Sie eine härtere Zeit zu tun, dass haben. Was Sie tun müssen, ist ein Wrapper um $ ressource und seine Instanzen zu erstellen. Das Problem, das Sie in dem Run ist diese Codezeile aus Winkel resource.js:

var value = this instanceof Resource ? this : (action.isArray ? [] : new Resource(data)); 

Hier wird der Rückgabewert von $ Ressource eingerichtet ist. Was passiert, ist "Wert" wird ausgefüllt und zurückgegeben, während die Ajax-Anfrage ausgeführt wird. Wenn die Ajax-Anforderung abgeschlossen ist, wird der Wert in "Wert" oberhalb, aber durch Referenz (mithilfe der angle.copy() -Methode) zurückgegeben. Jedes Element des Arrays (für eine Methode wie query()) ist eine Instanz der Ressource, auf der Sie arbeiten.

So eine Art und Weise Sie diese Funktionalität erweitern könnte, wäre so etwas wie dieses (nicht getesteten Code, so wird wahrscheinlich ohne einige Anpassungen nicht) sein:

var myModule = angular.module('myModule', ['ngResource']); 
myModule.factory('Book', function($resource) { 
    var service = $resource('/authors/:authorId/books'), 
     origQuery = service.prototype.$query; 

    service.prototype.$query = function (a1, a2, a3) { 
     var returnData = origQuery.call(this, a1, a2, a3); 
     returnData.myCustomMethod = function() { 
      // Create your custom method here... 
     return returnData; 
     } 
    } 

    return service; 
}); 

Wieder Sie damit zu verwirren haben eine bisschen, aber das ist die Grundidee.

2

Mit Blick auf den Code in angular-resource.js (zumindest für die 1.0.x-Serie) scheint es nicht, dass Sie in einem Callback für jede Art von Standardverhalten hinzufügen können (und dies scheint wie das richtige Design mir).

Wenn Sie nur den Wert in einem einzigen Controller verwenden, können Sie in einem Rückruf passieren, wenn Sie query auf die Ressource aufrufen:

var books = Book.query(function(data) { 
    data.hasBookWithTitle = function (title) { ... }; 
]); 

Alternativ können Sie einen Dienst erstellen, die die Bücher Ressource ziert , leitet alle Aufrufe an/abfragen/speichern/etc. und dekoriert das Array mit Ihrer Methode. Beispiel zupfen hier: http://plnkr.co/edit/NJkPcsuraxesyhxlJ8lg

app.factory("Books", 
    function ($resource) { 
    var self = this; 
    var resource = $resource("sample.json"); 

    return { 
     get: function(id) { return resource.get(id); }, 
     // implement whatever else you need, save, delete etc. 
     query: function() { 
     return resource.query(
      function(data) { // success callback 
      data.hasBookWithTitle = function(title) { 
       for (var i = 0; i < data.length; i++) { 
       if (title === data[i].title) { 
        return true; 
       } 
       } 
       return false; 
      }; 
      }, 
      function(data, response) { /* optional error callback */} 
     ); 
     } 
    }; 
    } 
); 

Drittens, und ich denke, das ist besser, aber es hängt von Ihren Anforderungen können Sie nehmen nur den funktionalen Ansatz und setzen Sie die hasBookWithTitle Funktion auf dem Controller, oder wenn die Logik sein muss geteilt, in einem Versorgungsdienst.

Verwandte Themen