angular $http.post returns code 302 - angularjs

I have the following php:
public function getLoggedInUser()
{
if($this->isAjax())
{
exit (json_encode($_SESSION['User']));
}
}
And the following angular:
userModule.controller('UserController', [ '$http', function($http)
{
var userCtrl = this;
this.user = {};
$http.post('/User/getLoggedInUser', {request: 'ajax'}).success(function(data)
{
userCtrl.user = data;
});
}]);
i get code 302 but no result is found and the php script is not running.
What am i doing wrong?
Update
After debugging i the core of my PHP i can see that the variable request is not send to the server.
Why isnt it?

Note I’m no PHP expert, but I did some testing relating to one other AngularJS post request few days ago, which is quite similar to this one. So my solution here is based on my experience relating to that previous PHP post data experience. Also php manual for $_SESSION was used here.
First of all I’d put your php code in a getLoggedInUser.php file like below:
<?php
if ($_SERVER["REQUEST_METHOD"] === "POST")
{
echo $_SESSION["User"];
}
?>
and then make some changes to the
UserController
//added $scope in the controller's function parameters, just in case
userModule.controller('UserController', [ '$http', function($scope, $http)
{
var userCtrl = this;
this.user = {};
//let’s pass empty data object
var dataObj = {};
$http.post('User/getLoggedInUser.php', dataObj).
success(function (data, status, headers, config)
{
console.log("success");
userCtrl.user = data;
//if the above doesn’t work, try something like below
// $scope.userCtrl.user = data;
})
.error(function (data, status, headers, config)
{
console.log("error");
});
}]);
I hope this helps with the issue.
Some notes: AngularJS is quite new to me, and if someone has different view how this post call should be made, then feel free to comment on this solution :-) Btw, I looked on some other php post issue solutions (without AngularJS) like this one, and I’m still uncertain what’s the best way of handling this post issue.

Related

Passing same parameter, multiple times in same query to Rest service using $resource

I am consuming this Rest web service from my AngularJS application and I'm using $resource to pass parameters and get my data.
I have a particular service that can take the same parameter multiple times like this in my Postman session:
/myService/Accounts?acctId[]=7029&acctId[]=3324
I've tried to pass a generated string to my $resource query methods placeholder but it ends up escaping all my brackets and not working.
I also tried not using a placeholder and passing the same parameter twice, it doesn't fail but it takes the last value so that does not work either.
$scope.resultsColl = rfpService.searchAccountName.query({
acctName: $scope.accountName,
acctRole: acctRoleParams,
acctRole: acctRoleParams2
});
Hopefully someone has had this same issue? Any ideas?
From the research I've done on other posts it looks like you can't dynamically generate using $resource. My working solution was to switch to $http, this way I could dynamically generate multiple acctRole[] params:
var acctRoleParams = '';
if(corporate === true)
{
acctRoleParams = '&acctRole[]=C';
};
if(smallBiz === true)
{
acctRoleParams += '&acctRole[]=B';
};
$http.get("https://myRestServiceUrl/services/customer/accounts?acct=" + $scope.account + acctRoleParams)
.success(function (data, status, headers, config) {
$scope.gridOptions.data = data.data.detailsByAcct;
})
.error(function (data, status, headers, config) {
showToast("An error occurred during the request");
})
.finally(function () {
$scope.isGridLoading = false;
});
I wanted to post this in case anyone else has been struggling to do the same thing.

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!

Can't get only the header in AngularJS (v1.3.15) using $resource and method 'HEAD'

In Angular (v1.2.19), I was able to do something like this in a factory :
myApp.factory('GetNumber', ['$resource',
function($resource) {
var get_headers = $resource('some/url', null, {
get_number: {
method: 'HEAD',
transformResponse: function(data, headers) {
var count = headers()['x-number'];
return count;
}
}
});
return get_headers;
}
]);
Call it from my controller like this:
$q.all({
'item1': GetNumber.get_number().$promise,
'item2': SomeOtherService.get().$promise
})
.then(function(results) {
$scope.newNumber = results.item1.value;
});
And I could get the custom header back without having to retrieve the whole header.
Now in v1.3.15, it doesn't work. I can see the header in Chrome with 'x-number' in the header, but if I put a breakpoint in Chrome on the 'var count' line, I never hit it (and I do hit it with v1.2.19).
I've verified that using $http.head works, so if I have this in my controller:
$http.head('some/url')
.success(function(data, status, headers, config) {
var count = headers()['x-number'];
$scope.newNumber = count ? count : 0;
});
I get my scoped value.
I've noticed that there aren't a whole lot of examples of people using the http 'HEAD' method and I'm wondering if there's a reason that I haven't located yet through searching?
I did find this StackOverflow question and answer HTTP Get: Only download the header? (HEAD is not supported) and while I agree with the statement, I don't want the overhead of requesting the headers and the body.
Any suggestions please?
Julie
Thank you to Kevin for suggesting that I use an error handler. I should've thought to try that myself, but I didn't.
Anyway, that lead me to the answer to my problem. To try and catch an error in $resource, it's suggested you use interceptors. I've never used them before and I utilized AngularJS documentation (https://docs.angularjs.org/api/ng/service/$http#interceptors) and changed the code in my factory to be:
myApp.factory('GetNumber', ['$resource',
function($resource) {
var get_headers = $resource('some/url', null, {
get_number: {
method: 'HEAD',
interceptor: { response: function(response) {
var count = response.headers()['x-number']:
return count ? count : 0;
}, responseError: function(rejection) {
console.log('rejection: ', rejection);
}}
}
});
return get_headers;
}
]);
I'm still not sure why transformResponse stopped working and I now need to use interceptor, but very happy I don't have to request the whole body now!
Julie

How to Prime $http $cache with AngularJS

When a user logs into the main page of my site, I typically load quite a bit of data on the home page. much more than when they come to a specific url on the page. When they hit the ome page, that actually fullfills the data requests of much of the data that I grab individually when they hit a specific page.
I like how the $http module works with $cache and I'm wanting to use the knowledge of my home page hit to populate the cache of calls I know the individual page will make.
That is, as an example, my home page calls /rest/clients which returns all clients while individual pages call /rest/client/101. What I want to do is make it so that if /rest/clients is called first, then when /rest/client/101 is called an new fresh xhr call does not have to be made but the data can be gotten from the cache as if /rest/client/101 had already been called.
I've never done a decorator before but I'm thinking maybe a decorator on the $http service? I looked through the $http code and it seemed the cache is stored in closure to the actual http call and not exposed except on the next Get.
Has anyone done this or similar? I could not find it. Any specific pseudo coding suggestions would be very welcome.
In your data service you have 2 methods, getAll and getOne.
In the service define a reference to your getAll results promise.
Then in your getOne service check to see if that promise exists and if it does use it to filter out the one item that you need to satisfy your getOne need.
module.service('dataService', function($http){
var getAllPromise = null;
this.getAll = function(){
if (getAllPromise !== null){
getAllPromise;
}
getAllPromise = $http.get('clients');
return getAllPromise
};
this.getOne = function(id){
if (getAllPromise !== null){
return getAllPromise
.then(function(allData){
//logic here to find the one in the full result set
return theFoundItem;
};
}
return $http.get('clients/' + id);
};
});
I found the solution I asked for but implementing and making it testable is proving to be beyond my skills. I'm going to go with #brocco solution but for the permanent record I'm leaving the actual answer to what I was asking. I'm not marking this as the correct solution because #brocco solution is better for my real problem. So, thank you #brocco for the help.
You can see below what I'm basically doing is to create my own $cache with $cacheFactory. I then use the .put method of the new cache object to prime my cache. Then, subsequent calls to the client/1 url will get the cache'd record without ever having to call cache/1 in real live. The cache is loaded in the for loop from the first big call.
Thanks for everyones input on this.
var myApp = angular.module('myApp', []);
myApp.factory('speakersCache', function($cacheFactory) {
return $cacheFactory('speakersCacheData');
});
myApp.controller('personController', ['$scope','$http','speakersCache', function ($scope,$http,speakersCache) {
$scope.getAllSpeakers = function() {
$http.get('speakers.json',{cache: speakersCache}).
success(function (data, status, headers, config) {
debugger;
var i;
for(i=0;i<data.length;i++) {
var url = 'speaker/' + i;
speakersCache.put(url, data[i]);
}
}).
error(function (data, status, headers, config) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
};
$scope.getAllSessions = function() {
$http.get('sessions.json',{cache: speakersCache}).
success(function (data, status, headers, config) {
debugger;
}).
error(function (data, status, headers, config) {
// called asynchronously if an error occurs
// or server returns response with an error status.
});
};
$scope.getOneSpeaker = function() {
$http.get('speaker/1',{cache: speakersCache}).
success(function (data, status, headers, config) {
debugger;
}).
error(function (data, status, headers, config) {
debugger;
});
}
$scope.checkit = function() {
var x = speakersCache;
debugger;
};
}]);
If I understand you well, I have done something similar:
I have this code:
.factory('myOwnEntity', ['$filter',
function ($filter) {
var myOwnList = [];
return {
set : function (data) {
myOwnList = data;
},
get : function () {
return myOwnList;
},
find : function (id) {
return $filter('filter')(myOwnList, { itemId : id }).pop();
}
}
}
])
When I make the petition to the Web Service, I store the information like this:
$http.get(url, {
cache : true
})
.success(function (data) {
myOwnEntity.set(data);
defer.resolve(data);
});
return defer.promise;
Now, the next time I need some information, I just query my entity with the find method. Hope this is what you are looking for.

angular.js and untappd API, how to send a Get request

I'm trying to connect to Untappd API trought angular.js; the API docs says
Whenever you are making a call to the API, you MUST pass both your Client ID and Client Secret as GET params like below
http://api.untappd.com/v4/method_name?client_id=CLIENTID&client_secret=CLIENTSECRET
with angular I have done this simply controller
function UntappdController($scope,$http) {
$http.get('http://api.untappd.com/v4/user/badges/jonnyjava?client_id=XXX&client_secret=XXX').success(function(data) {
alert('ok');
}).
error(function(data, status, headers, config) {
alert('ko');
});
}
UntappdController.$inject = ['$scope', '$http'];
but it doesn't work. (I get always KO)
So I'have tried tro a RESTful service. In this way
angular.module('BadgeServices', ['ngResource']).
factory('Badge', function($resource){
return $resource('http://api.untappd.com/v4/user/badges/jonnyjava/', {}, {
query: {method:'GET',params:{client_id: 'XXX', client_secret: 'XXX'}, isArray:true}
});
});
But this doesn't works too...
What I'm doing wrong? I'm new to angular. It looks simple but I'm missing something fundamental...
The error function is passed these variables: data, status, headers, config. Check their contents - I'm sure the server has some why of specifying what went wrong.
Sorry, I forgot it! Here is what I get with the error function..
data: status:0 headers:function (name) {
"use strict";
if (!headersObj) headersObj = parseHeaders(headers);
if (name) {
return headersObj[lowercase(name)] || null;
}
return headersObj;
}config:[object Object]
Nothing helpful...
Solved! It was a CORS problem. If anyone is interest the solutions is here.
stackoverflow-Angularjs issue $http.get not working

Resources