javascript - node - Angular-extendiendo $ subobject de recursos con métodos personalizados
promesas en angular 6 (4)
En la mayoría de los casos, el resultado del método <custom-resource>.query()
es una matriz, que se puede ampliar fácilmente con algunos métodos (lógica de negocios) con el siguiente código (de fábrica):
var Data = $resource(''http://..'');
Data.prototype.foo = function() {return ...};
esto es perfecto para usar con ng-repeat / ng-class, así:
<tr ng-repeat="item in responseData" ng-class="{warning: item.foo()}">..</tr>
Mi problema es que cada respuesta de lista está encapsulada en un objeto que, además de la lista real, tiene algunas meta-propiedades (clasificación de información, etc.), por lo que el objeto final devuelto es así:
{ order_field: "name", items: [{..}, {..},{..}] }
Ahora, ¿cómo hago lo mismo que antes con ng-repeat / ng-class?
<tr ng-repeat="item in responseData.items" ng-class="????">..</tr>
el método anterior no funcionará ya que el método "foo" se define en responseData
y NO en item
objeto del item
¿Hay alguna manera de extender directamente la clase base utilizada para crear instancias de objetos en la lista?
¡Gracias!
Esta es una vieja pregunta, pero me encontré con este problema yo mismo. La solución de Gargc es el enfoque correcto, pero hay una mejora. transformResponse
acepta una matriz que pasa al servicio $http
. En lugar de reemplazar por completo la función de transformación, puede agregar su transformación a los valores predeterminados para realizar las actualizaciones que necesita:
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;
});
He encontrado ese problema antes, y la solución parece ser transformResponse
, como dice John Ledbetter en la otra respuesta.
De todos modos, si necesita mantener todo el objeto , y también tener la matriz en ''elementos'' llena de instancias del recurso, puede hacerlo con el siguiente truco:
Tomando el ejemplo de la respuesta de John y modificándolo un poco:
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;
}]);
Podrías poner los metadatos en un encabezado. Siempre pongo datos de búsqueda allí. De esta forma, su consulta devolverá una matriz, lo que creo que es algo bueno. Las consultas deberían devolver matrices de datos, no datos únicos.
Si está usando angular-resource 1.1.5 (que hasta donde yo sé realmente funciona bien con angular 1.0.7), hay una opción transformResponse
que puede especificar al anular $resource
métodos $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;
}]);
Si hace esto, ya no tendrá que extraer manualmente los elementos de la respuesta envuelta, y cada elemento será una instancia de .foo
que tenga acceso al método .foo
. Puedes escribir:
<tr ng-repeat="post in posts" ng-class="{warning: post.foo()}">..</tr>
La desventaja de esto es que pierde acceso a cualquiera de los campos externos en su respuesta que no están dentro de los elementos. Todavía estoy luchando por encontrar una forma de preservar esos metadatos.