RESTAngular - DELETE, not working as it should - angularjs

If i am not mistaken in RESTful services in order to remove a record you need to do this:
Delete a product: DELETE /api/product/id (reference)
But in RESTAngular when i do for example
product.remove();
A DELETE request is made to /api/product whith the whole product object in the Requests Body. This is not what i want!
Here is my code:
myApp.factory('RESTService', [ 'Restangular', function (Restangular) {
var restAngular = Restangular.withConfig(function (Configurer) {
Configurer.setBaseUrl('/myAPI/');
});
var service = {};
service.Product= restAngular.service('product');
return service;
}]);
GET one Product
RESTService.Product.one(id).get().then(function (response) {
$scope.product= response;
})
DELETE the Product
$scope.product.remove();
I want when i do product.remove() to send a DELETE Request to /myAPI/product/id. How can i do that?

// DELETE /accounts/123/buildings/456
Restangular.one("accounts", 123).one("buildings", 456).remove();

You can delete a record using RESTFul($http) Service like this
$http.delete('/myAPI/product' + id, {params: {id: id}});

Related

How to contact a non-standard API using Angular ngResource

The API I am using requires a non-standard where clause if I try to search for a particular non-id field. The endpoint I need is:
http://127.0.0.1:4001/api/testusers/findOne?userName=Anton
So this will find me the first record in the testusers table whose column (userName) = 'Anton'.
My standard service is:
angular.
module('shared.testUser').
factory('TestUser', ['$resource',
function($resource) {
return $resource('http://127.0.0.1:4001/api/testusers/:id', {id:'#id'},//parameters
{
update: {
method: 'PUT' // To send the HTTP Put request when calling this custom update method.
}
});
}
]);
and my calling function is:
self.checkUsersEntryDirection = function(){ //NOT WORKING
self.testuser = TestUser.get({ username: 'anton' }, function() {
console.log(angular.toJson(self.testuser));
}); // get() returns a single entry
}
Clearly this doesn't work and I can't use the standard get approach. Can anyone think how this can be achieved?
You could create a secondary factory TestUserByName, and make the following changes:
angular.
module('shared.testUser').
factory('TestUserByName', ['$resource',
function($resource) {
return $resource('http://127.0.0.1:4001/api/testusers/findOne?userName:username', null,
{
update: {
method: 'PUT' // To send the HTTP Put request when calling this custom update method.
}
});
}
]);
Call the get action method with two parameters:
var params = {id: "findOne", username: "anton"};
self.checkUsersEntryDirection = function(){
self.testuser = TestUser.get(params, function() {
console.log(angular.toJson(self.testuser));
}); // get() returns a single entry
}
The id parameter will override the default and username parameter will be added as a query string.
From the DOCS:
Each key value in the parameter object is first bound to url template if present and then any excess keys are appended to the url search query after the ?.
Given a template /path/:verb and parameter {verb:'greet', salutation:'Hello'} results in URL /path/greet?salutation=Hello.
--AngularJS ngResource $resource Service API Reference

Unable to create POST request to REST API with $resource in angularjs

I am learning about the MEAN stack, and have created a REST API which posts a review to a collection in MongoDB.
I have defined a service as given:
angular.module('myApp')
.constant('baseURL', 'http://localhost:8080/');
angular.module('myApp')
.service('addReviews', ['$resource', 'baseURL', function($resource, baseURL) {
this.getReviews = function() {
return $resource(baseURL+'reviews/', null, {'save': {method: 'POST'}});
};
}]);
Now, I am calling this service from my controller:
angular.module('myApp', ['ngResource'])
.controller('reviewController', ['$scope', 'addReviews', function($scope, addReviews) {
$scope.reviewSubmit = function() {
$scope.receivedReviews = false;
var review = {
// some data
};
$scope.reviews = addReviews.getReviews().query(
function(response) {
$scope.reviews = response;
$scope.receivedReviews = true;
},
function(response) {
$scope.reviews = response;
// print error message
}
);
console.log($scope.reviews); // showing empty array
};
}]);
In routes.js, I have configured my route as:
var Reviews = require('./models/reviews');
...
app.post('/reviews', function(req, res) {
Reviews.create(req.body, function(err, post) {
if (err) {
return res.send(err);
}
return res.json(post);
});
});
I am trying to post a new review to the Reviews collection. However, $scope.reviews is showing an empty array. I logged the requests, and it shows a GET request is being to /reviews instead of POST. I think I should use save() instead of query(), but I have seen some tutorials online where they used query() despite the method being PUT/POST in the service. I am really confused. Can anyone point out how I can post the data (in var review) to the Reviews collection?
There are some issues with your code on the angular side of things.
You want to use $resource as an all-purpose object to communicate with the API. It has built-in functionality to:
query: get all resources from a given API endpoint
get: a single resource, usually by specifying that resource's id
save: post, with an object sent across in the body of the request. NOTE: you don't need the {'save': {method: 'POST'}} in your $resource configuration, you get it for free.
remove and delete: self-explanatory
So you'd want to set up your reviews factory (incl. url constant) like:
angular.module('myApp', ['ngResource'])
.constant('baseURL', 'http://localhost:8080/')
.factory('Reviews', ['$resource', 'baseURL', function($resource, baseURL) {
return $resource(baseURL+'reviews/:id', {id: '#id'});
}]);
If you want to have access to all saved reviews in your controller, as $scope.reviews, you'd do something like:
angular.module('myApp')
.controller('reviewController', ['$scope', 'Reviews', function($scope, Reviews) {
// hit API endpoint to get all reviews
// will have to have app.get('/reviews', function(req, res) {...})
// configured in your node code
Reviews.query(function(data) {
$scope.reviews = data;
}, function(error) {
console.log(error);
});
// and if you want to take a user-written review, say $scope.userReview,
// from the view and save it to the database on click function submitReview()...
$scope.userReview = {
message: '',
createdTime: null
};
// ^ not sure what your ReviewSchema looks like on the backend, but for example...
$scope.submitReview = function() {
if ($scope.userReview.message.length) {
$scope.userReview.createdTime = Date.now();
Reviews.save($scope.userReview);
// ^ this will make POST request with the $scope.userReview object as the request body
}
};
}]);
The create method on your back end looks fine. The object (or maybe just string) you send across will have to match your review schema. You may want to log the request body to make sure you're getting what you expect.
Have a look at this short post on using $resource to interact with RESTful APIs, and (the slightly more confusing) angular $resource docs, for more information on the $resource service.
Hope this helps you!

Accessing liked images of instagram API with Angular

I'm trying to access the JSON of the liked media of a particular instagram user, in the documentation it says to use this:
https://api.instagram.com/v1/users/self/media/liked?access_token=ACCESS-TOKEN
as mentioned here:
https://instagram.com/developer/endpoints/users/
replacing ACCESS-TOKEN with the one given by instagram which I've done below:
(function(){
var app = angular.module('instafeed', []);
app.factory("InstagramAPI", ['$http', function($http) {
return {
fetchPhotos: function(callback){
var endpoint = "https://api.instagram.com/v1/users/self/media/liked/?";
endpoint += "?access_token=[ACCESS-TOKEN]";
endpoint += "&callback=JSON_CALLBACK";
$http.jsonp(endpoint).success(function(response){
callback(response);
});
}
}
}]);
app.controller('ShowImages', function($scope, InstagramAPI){
$scope.layout = 'grid';
$scope.data = {};
$scope.pics = [];
InstagramAPI.fetchPhotos(function(data){
$scope.pics = data;
console.log(data)
});
});
})();
obviously I have replaced ACCESS-TOKEN with mine, but nothing is given back, is there something incorrect?
EDIT: I added the callback but still it comes back as undefined.
To make this work using jsonp, add the following to your endpoint url:
&callback=JSON_CALLBACK
Your callback needs to be named 'JSON_CALLBACK'. Find out why here: https://docs.angularjs.org/api/ng/service/$http#jsonp
Otherwise, to make a simple GET request...
$http.get(endpoint).success(function(data){
callback(data);
});
It's jsonp, so my guess is that you should specify name of the callback function in your URL:
var endpoint = "https://api.instagram.com/v1/users/self/media/liked/?callback=callback";

RESTAngular - PUT, Create new record

I have created a service with RESTAngular in order to ease my communication with my REST API. Let's say that i have an object Person.
Here is my service:
myApp.factory('RESTService', [ 'Restangular', function (Restangular) {
var restAngular = Restangular.withConfig(function (Configurer) {
Configurer.setBaseUrl('/myAPI/');
});
var service = {};
service.Person= restAngular.service('person');
return service;
}]);
I can successfully:
GET the list of Person
RESTService.Person.getList().then(function (response) {
$scope.persons = response.plain();
})
GET one Person
RESTService.Person.one(id).get().then(function (response) {
$scope.person = response.plain();
})
POST (Update) Person
RESTService.Person.post($scope.person).then(
function (successResponse) {
// success stuff
},
function (errorResponse) {
console.log("fail", errorResponse.status);
}
)
But i can't do PUT (create a new record). Now let's say i have a form and the form's data is being kept in $scope.formData. I want to do make a PUT request passing the object contained in $scope.formData to my API. How do i do that?
EDIT: For clarification my API is REST, so i do
GET - /myAPI/person to get the list of all the persons
GET - /myAPI/person/123 to get the person with id=123
POST - /myAPI/person/123 to update the person with id=123
PUT - /myAPI/person to insert a new person in my database
When creating a person for which you don't know the id yet, your API should accept a POST on myAPI/person. I assume Restangular expects that.
You don't want to accept a PUT, because the request is not idempotent. This is part of the semantics of a PUT and you want to adhere to that.
This SO question explores this in more detail: PUT vs POST in REST

Getting a single result with angularjs factory in MEAN stack

I'm trying to grab a single result from my expressjs api from within my AngularJS factory.
The factory looks like this and grabs all posts from my api(written in expressjs and getting data from mongodb), which is working fine:
angular.module('bonsaiService', ['ngResource']).
factory('bonsaiService', function($q,$resource) {
var bonsaiResource = $resource('http://localhost:8888/api/bonsais/:bonsaiId',{},{
get:{
method: 'GET',
params:{bonsaiId:''},
isArray: true
}
});
return {
get:function(){
var q = $q.defer();
bonsaiResource.get({
},
function(resp){
q.resolve(resp);
},function(httpResponse){
q.reject(httpResponse);
});
return q.promise;
}
//find by id
};
});
What i've tried so far is adding :bonsaiId after the $resource url and adding params for that id like this: params:{bonsaiId: ''}.
The server part (expressJS) look like this:
router.route('/bonsais/:bonsaiId')
.get(function(req,res){
Bonsai.findOne(req.params.bonsaiId,function(err,bonsai){
if(err)
res.send(err);
res.json(bonsai)
})
})
When I call a local url (with and existing _id from mongodb) it works fine and returns my data in json :
http://localhost:8888/api/bonsais/536be2e2ae54668818000001
Now in the controller im trying to get this data in my scope, which is not working.
bonsaiService.get({bonsaiId:$routeParams.bonsaiId}).then(
function(data){
$scope.trees = data;
console.log(data);
});
How do I make this work?
You could use a more simple approach here.
The query method for $resource already defines a GET on an array, which is QUERY.
Why not write your service this way :
.factory('bonsaiService', ['$resource',
function($resource) {
return $resource('http://localhost:8888/api/bonsais/:bonsaiId', {
bonsaiId: '#bonsaiId'
});
}
])
And in your controller, it would work like this :
bonsaiService.query({
bonsaiId: $routeParams.bonsaiId
}, function success() {
//Your code
}, function err() {
//Your code
});
Don't forget to inject the service in the controller or the app file, if it's not done already.

Resources