I'm trying to overwrite the query()-method of AngularJS $resource with a custom $http-GET. However, it doesn't seem to overwrite the result of the operation. It returns an object with method, data and headers, not data.rows[].
angular.module('couchdb', ['ngResource']).
factory('Project', function($resource, $http) {
var Project = $resource('http://couchdb/mydb', {}, {
'update': { method: 'PUT' },
'query': {method:'GET', isArray: false}
}
);
Project.query = function() {
return $http({method: 'GET', url: 'http://couchdb/mydb/_design/projects/_view/index'}).
success(function(data, status, headers, config) {
return data.rows;
}).
error(function(data, status, headers, config) {
$scope.data = data || "Request failed";
$scope.status = status;
});
};
return Project;
});
How can I only get the rows of the result for the resource?
ngResources don't need to rely on the $http service. You don't need to be redefining the Project.query function - as you've already indicated it as an action of the Project $resource (in addition to it being included by default).
This means that the Project.query function is ready to go, and does not need re-definition. You can literally just do Project.query() to get results. It supports callbacks for success/failure, so Project.query({}, successCallback, failureCallback) will submit no arguments, and give you access to the returned data.
I suggest you read the AngularJS $resource documentation carefully, as they provide plenty of good examples. A basic example is also included in Step 11 of the Angular Tutorial.
Related
I have a http service which will call external json files and load it into a grid.
My problem is i need to create a custom http service so that i could use the same in different controllers. The function of that custom service should be the same (requesting external Json file)
$http.get('../JSON/permanentEmployees.json').
success(function(data, status, headers, config) {
$scope.masterArray = data;
}).
error(function(data, status, headers, config) {
$scope.errorMessage = "Requested grid data file does not exist";
});
This is my current http service. Any help would be appreciated.Please use angularjs only
wrap the code in a factory and use it. I think its better to use a factory in this situation, refer here. P.S. unable to create a mockup of the request to JSON, please check with your JSON.
JSFiddle: here
app.factory('customHTTPService', function($http){
return {
getRequest: function(url) {
return $http.get(url).
success(function(data, status, headers, config) {
return {data: data, errorMessage: "Success"};
}).
error(function(data, status, headers, config) {
return {data: "", errorMessage: "Requested grid data file does not exist"};
});
}
}
});
In the controller you can do
app.controller('MyController', function MyController($scope, customHTTPService) {
$scope.data = customHTTPService.getRequest('../JSON/permanentEmployees.json').data;
});
I'm trying to read a properties file in angular, It's neccesary to have this file at the root of my project without any kind of angular stuffs, just a simple file, like java.
This is what I'm doing.
Creating a angular.properties file.
angular.properties
{
"url": "http://localhost"
}
This is my controller where I invoke my service method:
controller
captchaService
.all()
.then(function(data) {
...
}, function (data) {
...
});
This is my service class:
service
'use strict';
angular.module('app.service', [])
.factory('myService',
['$http', '$q',
function ($http, $q) {
var _URL = "";
function getValuesFromProperties() {
$http({
method : 'GET',
url : 'angular.properties'
}).success(function (data, status, headers, config) {
_URL = data.url;
}).error(function (data, status, headers, config) {
...
});
}
function all() {
getValuesFromProperties();
var deferred = $q.defer(),
promise = deferred.promise;
sessionStorage.removeItem('X_CAPTCHA_TOKEN');
$http({
method : 'POST',
url : _URL
}).success(function (data, status, headers, config) {
...
}).error(function (data, status, headers, config) {
...
});
return promise;
}
return {
all : all,
getValuesFromProperties : getValuesFromProperties
};
}]);
But here in my services class I have two $http running on an asynchronous way for that reason I can not get the value of url everything else works perfect. How can resolve this? Maybe there is another way to do this. I don't want to create a constant class because this file it's placed at the root of the project and it will be configure for others, they don't need to enter inside a lot of folders and check the code, search and edit. Any idea?
Somewhat new to Angular and javascript. I have the following controller written use a factory service to access a local JSON file. Most of this code is derived (or completely taken) from this post by Dan Wahlin. I am unable to access the $scope.books variable outside of the function and cannot figure out why. The console.log inside the function gives me the object I am looking for, but the one outside returns undefined. What am I doing wrong here? Thanks.
app.controller('FormController', ['$scope', 'tocFactory', function ($scope, tocFactory) {
$scope.books;
getBooks();
function getBooks() {
tocFactory.getBooks().
success(function(data, status, headers, config) {
$scope.books = data;
console.log($scope.books);
}).
error(function(data, status, headers, config) {
// log error
})
}
console.log($scope.books);
}]);
Because you are making an ajax and then executing the next line of code. Which doesn't mean you have guarantee that your ajax response is ready on execution of next line of code.
You could always gets its response value inside the success function of $http which gets called when ajax call executed successfully.
Read here How asynchronous call works?
actually this isn't an issue of scope, but timing. The getBooks function is executed asynchronously, so when your console log happens it most likely will not have been bound to anything. You could test this easily with interval to see how this is happening:
app.controller('FormController', ['$scope', 'tocFactory', function($scope, tocFactory) {
$scope.books;
getBooks();
function getBooks() {
tocFactory.getBooks()
.success(function(data, status, headers, config) {
$scope.books = data;
console.log($scope.books);
})
.error(function(data, status, headers, config) {
// log error
})
}
setInterval(function(){
console.log($scope.books);
}, 1000);
}]);
You can use $q service to handle asynchronous code with promises :
app.controller('FormController', ['$scope', '$q', 'tocFactory', function ($scope, $q, tocFactory)
{
var getBooks = function()
{
var deferred = $q.defer();
tocFactory.getBooks().
success( function(data, status, headers, config)
{
$scope.books = data;
deferred.resolve();
} ).
error( function(data, status, headers, config)
{
deferred.reject();
} );
return deferred.promise;
};
getBooks().then( function(res)
{
console.log($scope.books); // success : your data
}, function(res)
{
console.log($scope.books); // error : undefined
} );
console.log($scope.books); // undefined
} ] );
I haven't tested this code but it should work and show you promises principle.
More about $q service : https://docs.angularjs.org/api/ng/service/$q
My application has the following $resource calls. From what I can see this could be replaced with $http.
$resource('/api/:et/', { et: $scope.data.entityType })
.save(data, newSuccess, error)
.$promise.finally(last);
$resource('/api/:et/:id', { et: $scope.data.entityType })
.delete({ id: entityId }, deleteSuccess, error)
.$promise.finally(last);
$resource('/api/:et/:id', { et: $scope.data.entityType }, { update: { method: 'PUT' } })
.update({ id: entityId }, data, editSuccess, error)
.$promise.finally(last);
I have checked the $http documentation but I cannot see how to add the calls to the xxxSuccess, error functions and how to do the .$promise.finally(last).
Can someone explain how I could replicate this functionality using $http ?
$http is for general purpose AJAX. In most cases this is what you'll be using. With $http you're going to be making GET, POST, DELETE type calls manually and processing the objects they return on your own.
$resource wraps $http for use in RESTful web API scenarios.
Syntax
$http({
method : 'GET',
url : '/someUrl',
param : { paramKey : paramValue}, // optional
headers : 'someHeaders' // optional
}).success(function(data, status, headers, config)
{
// this callback will be called asynchronously
// when the response is available
}).error(function(data, status, headers, config)
{
// called asynchronously if an error occurs
// or server returns response with an error status.
});
$http Documentation - https://docs.angularjs.org/#!/api/ng/service/$http
Maintaing Promise in $http
app.factory('myService', function($http) {
var myService = {
async: function() {
// $http returns a promise, which has a then function, which also returns a promise
var promise = $http.get('/someUrl').then(function (response) {
// The then function here is an opportunity to modify the response
console.log(response);
// The return value gets picked up by the then in the controller.
return response.data;
});
// Return the promise to the controller
return promise;
}
};
return myService;
});
app.controller('MainCtrl', function( myService,$scope) {
// Call the async method and then do stuff with what is returned inside our own then function
myService.async().then(function(d) {
$scope.data = d;
});
});
Take a look at this article Angular Promises, It will definitely benifit you in acheving such scenerios.
$resource is a further abstracted version of $http. If you are already using $response you may find it's not useful to change your logic to use $http. That said -
https://docs.angularjs.org/api/ng/service/$http
General usage
The $http service is a function which takes a single argument — a configuration object — that is used to generate an HTTP request and returns a promise with two $http specific methods: success and error.
$http({method: 'GET', url: '/someUrl'}).
success(function(data, status, headers, config) {
// this callback will be called asynchronously
// when the response is available
}).
error(function(data, status, headers, config) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
I have been trying AngularJS for a experimental project and I came along with this problem.
In my html I want to display a list of items
Index.html
<h1>Some list</h1>
<div ng-controller="datlist">
<div ng-repeat="item in items">
<div>Item description: {{item.description}}</div>
<div>Item name: {{item.name}}</div>
</div>
</div>
At first I was using a simple controller to get the information and update the view just using this:
controllers.js (original)
function datlist($scope,$http){
$http({method: 'GET', url: 'http://localhost:61686/getdatlist?format=json', headers: {'Access-Control-Allow-Origin': 'localhost:*'}}).
success(function(data, status, headers, config) {
$scope.items=data.itemsToReturn;
console.log(data);
}).
error(function(data, status, headers, config) {
console.log("fail");
});
}
This was working pretty well and I could get the list of items. Whilst, by changing my structure to use a factory to make the same request and bind it to $scope.items it doesn't work. I tried a lot of variations of $watch but I couldn't get it to update $scope.items. I found something about $apply but I really can't understand how to use it.
controllers.js (new one)
var datModule = angular.module('datModule',[]);
datModule.controller('datlist', function ($scope, datfactory){
$scope.items = datfactory.getlist();
$scope.$watch($scope.items, $scope.items = datfactory.getlist());
});
datModule.factory('datfactory', function ($http){
var factory = {};
factory.getlist = function(){
$http({method: 'GET', url: 'http://localhost:61686/getdatlist?format=json', headers: {'Access-Control-Allow-Origin': 'localhost:*'}}).
success(function(data, status, headers, config) {
console.log(data.itemsToReturn); //I get the correct items, all seems ok here
return data.itemsToReturn;
}).
error(function(data, status, headers, config) {
console.log("fail");
});
}
return factory;
});
Any ideas about this will be great.
PS: I found a lot of posts talking about this issue but none of them helped me to get a full solution.
Thanks
Using a watch for that is kinda ugly.
try this:
datModule.factory('datfactory', function ($http, $q){
this.getlist = function(){
return $http.get('http://localhost:61686/getdatlist?format=json',{'Access-Control-Allow-Origin': 'localhost:*'})
.then(function(response) {
console.log(response); //I get the correct items, all seems ok here
return response.data.itemsToReturn;
});
}
return this;
});
datModule.controller('datlist', function ($scope, datfactory){
datfactory.getlist()
.then(function(arrItems){
$scope.items = arrItems;
});
});
This is how you use promises for async matter.
UPDATE (15.01.2015): Now even sleeker!
The issue is nothing to do with the scope digest cycle. You are trying to return from inside a callback directly, which is not asynchronously possible.
I recommend you either use a promise, or return the http promise directly.
var factory = {};
factory.getlist = function(){
return $http({method: 'GET', url: 'http://localhost:61686/getdatlist?format=json', headers: {'Access-Control-Allow-Origin': 'localhost:*'}});
}
return factory;
To return the promise directly, and handle the success/fail at factory.getlist().success()
Alternatively, use your own promise if you want to wrap additional logic around the request.
var datModule = angular.module('datModule',[]);
datModule.controller('datlist', function ($scope, datfactory){
$scope.items = [];
datfactory.getlist().then(function(data) { $scope.items = data });
});
datModule.factory('datfactory', function ($http, $q){
var factory = {};
factory.getlist = function(){
var defer = $q.defer();
$http({method: 'GET', url: 'http://localhost:61686/getdatlist?format=json', headers: {'Access-Control-Allow-Origin': 'localhost:*'}}).
success(function(data) {
// alter data if needed
defer.resolve(data.itemsToReturn);
}).
error(function(data, status, headers, config) {
defer.reject();
});
return defer.promise;
}
return factory;
});
try to initialize $scope.items = []; at controller, before call $http
I hope it helps you.
Well it looks perfect but you can use $apply like this.
datModule.controller('datlist', function ($scope, datfactory){
$scope.$apply(function() {
$scope.items = datfactory.getlist();
});
});
I think another elegant solution to this problem could be - if you are using one of the routing libraries, in my case it is the UI-Router, but could be also ngRoute, is making your controller dependent on the response of the promise, eg. adding a resolve property to the adequate state/route which doesn't let the controller load until the promise is solved and the data is ready, so in your config:
.state('datpage', {
url: '/datpage',
controller: 'DatpageController',
resolve:{
datData: function (datfactory) {
return datDataService.getData("datDataParam");
}]
},
templateUrl: 'views/datpage.html'
})
And inject the datData dependency in your controller, where you can apply it directly to the $scope:
.controller('DatpageController', function ($scope,datData) {
$scope.datPageData = datData; ...