6

次のように、クエリから配列を返すリソースがあります。

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

このクエリから返された配列にプロトタイプ メソッドを追加することは可能ですか? (注、しないでくださいarray.prototype)。

hasBookWithTitle(title)例えばコレクションになどのメソッドを追加したい。

4

3 に答える 3

5

ricick からの提案は良いものですが、返される配列に実際にメソッドが必要な場合は、それを行うのが難しくなります。基本的に必要なことは、$resource とそのインスタンスの周りにちょっとしたラッパーを作成することです。あなたが遭遇する問題は、angular-resource.js からの次のコード行です。

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

ここで $resource からの戻り値を設定します。何が起こるかというと、ajax リクエストの実行中に「値」が取り込まれて返されます。ajax リクエストが完了すると、値は上記の「値」に返されますが、参照によって (angular.copy() メソッドを使用して) 返されます。配列の各要素 (query() などのメソッドの場合) は、操作対象のリソースのインスタンスになります。

したがって、この機能を拡張する方法は次のようになります (テストされていないコードなので、おそらく調整なしでは機能しません)。

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;
});

繰り返しますが、少しいじる必要がありますが、それが基本的な考え方です。

于 2013-03-08T03:46:03.367 に答える
2

angular-resource.js のコード (少なくとも 1.0.x シリーズの場合) を見ると、あらゆる種類のデフォルト動作のコールバックを追加できるようには見えません (これは私にとって正しい設計のようです)。

単一のコントローラーで値を使用しているだけの場合はquery、リソースで呼び出すたびにコールバックを渡すことができます。

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

または、Books リソースを装飾し、すべての呼び出しを get/query/save/etc. に転送し、メソッドで配列を装飾するサービスを作成できます。プランクの例: 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 */}
        );
      }
    };
  }
);

第三に、これはより良いと思いますが、要件によって異なります。機能的なアプローチを取り、コントローラーに hasBookWithTitle 関数を配置するか、ロジックを共有する必要がある場合はユーティリティ サービスに配置できます。

于 2013-03-08T19:02:53.650 に答える