I'm trying to get familiar with $resource in order to use RESTful Web Services.
So, for the attempt, I declared a factory like this :
'use strict';
angular.module('BalrogApp').factory('Req', ['$resource', function($resource) {
return $resource('http://localhost:8000/api/catalog/requests/:id', {id: '#id'}, {
'update': { method: 'PUT'},
'query': { method: 'GET'}
});
}]);
In my Controller I have this :
angular.module('BalrogApp').controller('requestsController', function(Req, $route, $rootScope, $scope, $location, $routeParams) {
this.$route = $route;
var controllerScope = this;
this.r = Req.get({ id:4 });
console.log(this.r);
This works fine, in my console, I can see my object with the data retrieved from the services for the item with id 4.
However I'm not sure I'm properly retrieving the data since the object i'm storing in r contains an id like it should in the object details (clicking on "Object" in the browser console displays the object details including its id) but the object itself (r) displayed on the console contains only 2 fields and is presented as follows : Object { $promise: Object, $resolved: false }.
So, in the end, console.log(this.r); works but console.log(this.r.id); doesn't even if r is supposed to contain an id just like in the object details from the browser inspector.
Also, how can I configure this service in order to be able to use get() with the id parameter just like I'm doing which results in calling http://localhost:8000/api/catalog/requests/:id but also without the id parameter which results in calling http://localhost:8000/api/catalog/requests
As the call to the REST API is asynchronous you shout wait for the returned promise to resolve when using the Req.get({ id:4 });
Use:
Req.get({ id:4 }).$promise.then(function(result){
console.log(JSON.stringify(result));
});
instead.
For the second part of your question: Using data without an id property should be fine. This data, however, will be transfered in the request body and not as a request parameter.
Related
I'm using angular's $httpBackend for unit testing a bunch of API functionality. The application makes use of $resource for most API endpoints, but has a single raw $http call (to send data along with a DELETE request, not my choice).
The model has a simple delete method like this:
this.delete = function(target) {
return $http({method: 'DELETE', url: '/api/delete' + this.id, data: target});
};
And a simple test case, which fails with No pending request to flush:
it('calls the API', function() {
httpBackend.expect('DELETE', '/api/delete').respond(200, '');
scope.obj.delete(1);
httpBackend.flush();
});
This test setup seems to work fine with any endpoints using $resource, but fails as soon as I use $http. I verified that the .delete() method has been called, and that it returns a promise as expected.
Did I miss something in the documentation?
I feel like tons of people do this all the time, and yet I have been unsuccessful in finding similar examples.
I am getting data from the backend using angularJS ($http.post) to a controller in a javascript file, and presenting it in one html. The data is received after sending a search query from that html. Now, I want to "export" that data to another JS file and to present some of it again, in a new html. The problem is that I have access to that data only through the Search Controller during the searching session, and I probably need to store it somehow or send it to another controller/ JS file.
Unfortunately, I cannot use $cookies. Also, I am trying to avoid sending a new request through the server if I don't have to.
I have read a some about services in angular, however, I am new to angular (and UI in general), and for some reason was unable to implement this for my specific case.
Here is an example of the relevant controller, after getting a search request from the html page:
app.controller('SearchCtrl', ['$scope', '$http',
function($scope, $http) {
$scope.searchJSON = {
searchToken: [],
searchOption: []
$scope.sendSearch = function() {
//preparing JSON to send request to server
$scope.searchJSON["searchToken"] = this.search.searchToken;
$scope.searchJSON["searchOption"] = this.search.searchOption;
var json = $scope.searchJSON;
//sending and getting response (JSON object)
$http.post("http://some_host", json)
.success(function(response) {
$scope.collections = response.searchResults;
});
};
}]);
So the data I am interested in passing on to another JS file is in $scope.collections , which is a JSON file (I don't want use the same JS file for both html pages, so was hoping to call that data from a new controller in a new JS file).
Will appreciate any answers, leads, or similar examples from the web. Thank folks!
One possible way to solve this is by using sessionStorage/localStorage on $window. You can store your data there and after redirecting to another file, you can use it by invoking.
You are right to bring up services because that is how I would personally implement this. Create a service to handle the search request and also to store the result via promises:
angular.module('yourModule')
.factory('searchService', function($http, $q) {
var searchService = {
resultsPromise: null,
sendSearch: function(token, option) {
var dfd = $q.defer();
var json = {
searchToken: token,
searchOption: option
};
$http.post("http://some_host", json).then(
function(response) {
// resolve your deferred
dfd.resolve(response.data);
},
dfd.reject
);
this.resultsPromise = dfd.promise;
return dfd.promise;
}
};
return searchService;
});
Then in your current controller, just do:
app.controller('SearchCtrl', ['$scope', 'searchService',
function($scope, searchService) {
$scope.searchJSON = {
searchToken: [],
searchOption: []
$scope.sendSearch = function() {
searchService.sendSearch($scope.searchJSON.searchToken, $scope.searchJSON.searchOption);
};
Then in your other file, simply look at the currentResults of the same service:
app.controller('OtherCtrl', function($scope, searchService) {
if (searchService.resultsPromise) {
searchService.resultsPromise.then(function(results) {
$scope.results = results;
});
}
});
You can ditch the $http service and use $resource instead. From there you can use $cacheFactory as seen in this post: How to cache an http get service in angularjs
An alternative solution is http://jmdobry.github.io/angular-cache/ which works well with ngResource and can also easily be configured to sync to localStorage, so requests don't need to be re-done after page refresh.
`$resource('my/kewl/url/:key', { key: '#key' }, {
'get': { method: 'GET',
cache: $angularCacheFactory('MyKewlResourceCache', {
storageMode: 'localStorage' })
}
});`
As a beginner in Spark framework and AngularJS I was trying to build a simple REST application. However I apparently can’t retrieve data from the server and display using Angular.
I started with simple task:
#Data
public class Todo {
private String title = "foo";
private String description= "bar" ;
}
In order to display the todo in the browser I send a JSON object as a response to get request.
get("/tasks", (request, response) -> {
response.type("application/json");
Todo todo = new Todo();
ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationFeature.INDENT_OUTPUT, true);
String data = mapper.writeValueAsString(todo);
return data;
});
The Angular part looks as follows:
(function() {
var app = angular.module('todoapp', []);
app.controller('TaskController', ['$http', function($http) {
var store = this;
store.tasks = [];
$http.get('/tasks').success(function(data) {
store.tasks = data;
});
}]);
})();
And the index.html :
<ul ng-controller="TaskController as taskCtrl">
<li ng-repeat="task in taskCtrl.tasks">{{task.title}}, {{task.description}}</li>
</ul>
After running Spark and entering http://localhost:4567/tasks in the browser,it shows only JSON representation:
{
"title": "foo",
"description": "bar"
}
What am I doing wrong?
In your Spark code you are creating a '/tasks' endpoint, which you are attempting to hit with your angular code. When you try to run this in the browser, you are just hitting your '/tasks' api endpoint which is returning the expected response. You need to create another endpoint in Spark which will serve up the appropriate HTML and JavaScript code.
I'm not sure what version of angular you are using but in the version I use $http returns a different data structure than the one you show.
So to get the data from an $http request I would do something like,
$http({
url: '/tasks',
method: 'get'
}).then(function(result){
$scope.tasks = result.data;
});
The result.data is where the data structure on $http returns differ from what I see in your code.
Try console.log(data) to get a look at what the call is getting back.
I am trying to call a REST service using Angular 1.3 but keep getting an "Error: error:badcfg
Response does not match configured parameter".
I suspect it is in my controller where I call the $scope.data. I believe .data is correct but it is throwing this error.
Here is my service, including a test REST call:
var pfcServices = angular.module('pfcServices', ['ngResource'])
pfcServices.factory('pfcArticles', ['$resource',
function($resource){
return $resource('https://myrestcall.com/data, {}, {
query: {method:'GET'}
});
}]);
Here is my controller:
var pfcControllers = angular.module('pfcControllers', []);
pfcControllers.controller('pfcCtrl', ['$scope', 'pfcArticles', function ($scope, pfcArticles) {
$scope.data = pfcArticles.query();
}]);
Within IE, I get a CORS message of: XMLHttpRequest for https://pfc.azure-mobile.net/tables/articles required Cross Origin Resource Sharing (CORS). This does not occur within Chrome.
However, I am not sure if this is related, or just a bad call on my part. I have added my test site to the CORS in Azure Mobile Webservices where I am hosting the test REST call.
I am newer to Angular, so I am leaning towards a bad call on my part.
I am not sure why have set query properties on the resource. Either remove the configuration for query
return $resource('https://pfc.azure-mobile.net/tables/articles', {});
or set isArray true on the query configuration.
return $resource('https://pfc.azure-mobile.net/tables/articles', {}, {
query: {method:'GET',isArray:true}
});
The error is coming because Angular is not able to deserialize your response as it expects an object but the response from the call is an array.
The query method on $resource already has this flag set, but since you are redefining the query configurations this error is occurring. Do check the $resource documentation.
I am using nodeJS so the server will send the following json object to controller by doing:
data = {
"question": "theQuestion",
"answer": "theAnswer"
};
res.json(data);
Then in the controller, I want to manipulate the variable like:
data = QA.get();
$scope.q = data[question] + "Some additional info here";
QA is the service defined as:
angular.module('questionServices', ['ngResource'])
.factory('QA', function ($resource) {
return $resource('/qa');
});
However, the error message always tells me that data[question] is undefined. What is the right way to access the value? I have tried data.question. It doesn't work either.
I know I can simply show the json values by using ng-repeat in html but I want to be more flexible managing the values.
Seems you QA function you use $http or $resource to get the ajax response.
If you return $http.get/$http.post in you QA service, you can use this code to handle the json response:
QA.get().success(function(data){
console.log(data);
console.log(data.answer);
}).error(functoin(data){
//handle error here.
});
If you use $resource in your QA service, then you can use this code to handle that:
QA.get().$promise.then(function(data){
console.log(data);
console.log(data.answer);
}).then(function(error){
//handler error here.
});
Here is $http document.
Here is $resource document.
P.S you need to understand in ajax, javascript handle the request in async. That means when
exec these code:
$scope.data = QA.get()
console.log($scope.data); // QA.get() send a http request. Now data is still promise object.
you cannot get this response immediately. So if you try to log the data, or use console.log(data.answer) to get data.answer. you will get undefined
However in you html view. You can get the data with {{data|json}} . This is because angular will $watch your data. And once data($resource promise object) is change(means http request is finished), Angular will render your view automatically.
That's why in your view you can get data.answer. But in your controller, you cannot.
$scope.data = QA.get();
console.log(data);
or in your template: {{data | json}}
This will give you a hint