ほとんどの場合、<custom-resource>.query()
メソッドの結果は配列であり、次の(工場の)コードを使用していくつかのメソッド(ビジネスロジック)で簡単に拡張できます。
var Data = $resource('http://..');
Data.prototype.foo = function() {return ...};
これは、次のようにng-repeat/ng-classで使用するのに最適です。
<tr ng-repeat="item in responseData" ng-class="{warning: item.foo()}">..</tr>
私の問題は、実際のリストに加えて、いくつかのメタプロパティ(ソート情報など)を持つオブジェクトにすべてのリスト応答がカプセル化されるであるため、返される最終オブジェクトは次のようになることです。
{ order_field: "name", items: [{..}, {..},{..}] }
さて、ng-repeat/ng-classを使用して以前と同じことを行うにはどうすればよいですか?
<tr ng-repeat="item in responseData.items" ng-class="????">..</tr>
「foo」メソッドはresponseData
オブジェクトではなくitem
オブジェクトで定義されているため、前のメソッドは機能しません。
リスト上のオブジェクトのインスタンス化に使用される基本クラスを直接拡張する方法はありますか?
ありがとう!
私は以前にその問題を見つけました、そして、ジョン・レッドベターが他の答えで言うように、解決策はtransformResponse
であるようです。
とにかく、オブジェクト全体を保持する必要がある場合であり、リソースのインスタンスで満たされた 'items'の配列を持つ場合、次のトリックでそれを行うことができるかもしれません:
ジョンの答えから例を取り上げて、少し修正します。
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.1.5(angular 1.0.7)で実際にうまく機能することがわかる限り)を使用している場合は、transformResponse
オプションがあります$resource
メソッドをオーバーライドするときを指定します。
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;
}]);
これを行うと、ラップされた応答からアイテムを手動でプルする必要がなくなり、各アイテムは.foo
メソッドにアクセスできるPost
のインスタンスになります。あなたはただ書くことができます:
<tr ng-repeat="post in posts" ng-class="{warning: post.foo()}">..</tr>
これの欠点は、アイテム内にない応答の外部フィールドにアクセスできなくなることです。そのメタデータを保存する方法を見つけるのにまだ苦労しています。
これは古い質問ですが、自分でこの問題にぶつかりました。 gargcのソリューションは正しいアプローチですが、改善されています。 transformResponse
は、$http
サービスに渡される配列を受け入れます。変換関数を完全に置き換えるのではなく、デフォルトに変換を追加して、必要な更新のみを行うことができます。
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;
});
メタデータをヘッダーに入れることができます。私はいつもページングデータをそこに置きます。そうすれば、クエリは配列を返しますが、これは良いことだと思います。クエリは、単一のデータではなく、データの配列を返す必要があります。