how to get results of my webservice with jsonp? - angularjs

I want to call one of my webservices via jsonp with angularjs.
When i call http://example.com/files?callback=JSON_CALLBACK directly in my browser, i got :
["folder1", "folder2"]
When i call from angularjs with :
$http.jsonp('http://example.com/files?callback=JSON_CALLBACK')
.success(function(data){
console.log(data);
$scope.folders = data;
});
console.log does not appear....
What am i doing wrong ?
Must my webservice return
JSON_CALLBACK(["folder1", "folder2"])
? Should i do it manually in my api ? browser don't do that automatically ?

What you are currently returning (["folder1", "folder2"]) is not valid JSONP. The JSON result must be wrapped by a javascript function call in order to be valid JSONP.
For example, when you use the URL like this:
http://example.com/files?callback=JSON_CALLBACK
Angular will replace the JSON_CALLBACK parameter with an angular function name (created internally), like:
http://example.com/files?callback=angular.callbacks._0
Your server would then need to be able to read that callback parameter and return the result like this:
angular.callbacks._0(["folder1", "folder2"]);
This is not an automatic mechanism, you need to implement that logic on your web server.

Try Using Following code snippet.
(function($) {
var url = 'http://example.com/files?callback=JSON_CALLBACK';
$.ajax({
type: 'GET',
url: url,
async: false,
jsonpCallback: 'jsonCallback',
contentType: "application/json",
dataType: 'jsonp',
success: function(data) {
console.dir(data);
},
error: function(e) {
console.log(e.message);
}
});
})(jQuery);

bmleite was right, I had to implement this logic on my API.
In my example, my server is made with Silex :
public function index()
{
$callback = $this->request->get('callback');
$files = $this->app['file.manager']->getList();
$response = new \Symfony\Component\HttpFoundation\JsonResponse();
$response->setData($files);
$response->setCallback($callback);
return $response;
}
And it works perfectly now. Thank you.

Related

How to access ajax response data outside ajax function in angularjs

I am fetching some data via http get ajax.
$.ajax({
type: "GET",
url: "/userdata/",
success: function(response){
$scope.steps = response.no_of_steps;
$scope.calories = response.calories;
},
error: function(){
alert("error");
}
});
If i print it on console from inside the success function, it prints the value like:
success: function(response){
var $scope.steps = response.no_of_steps;
var $scope.calories = response.calories;
console.log($scope.steps, $scope.calories);
},
But if i print it on colsole outside my ajax request, it print undefined. how is that so?
$.ajax({
...
});
console.log($scope.steps, $scope.calories);
this is continuation of my comment on your post above
you could do that by using $scope.$emit("custom-event-name"); of angular,
here you are actually watching $scope.steps and $scope.calories for change once your ajax call completes signify this by using $emit of angular
and then listen for that event by $scope.$on("custom-event-name", function(){})
and log it there, Please do make sure your "custom-event-name" is same in $emit and $on
in success callback : initialize the value and use $emit to emit an event named initialized as :-
$scope.steps = response.no_of_steps;
$scope.calories = response.calories;
$scope.$emit("initialized");
and then listen for that event initialized
$scope.$on('initialized', function () {
console.log($scope.steps + ' and ' + $scope.calories);
});
Couple of mistakes here.... use $http instead of $ajax, secondly you are defining your variables inside your success function so the scope is limited once it comes out of it... define your function globally in your controller and then access it inside your success function.
var $scope.steps => wrong way
$scope.steps = "something"; => right way.
You don't need to append var keyword with $scope in angularjs.
$scope.steps;
$scope.calories;
$.ajax({
type: "GET",
url: "/userdata/",
success: function(response){
$scope.steps = response.no_of_steps;
$scope.calories = response.calories;
},
error: function(){
alert("error");
}
});
Use $scope variables if you want to bind to the view and var does not and is local to the function it was declared in.
This works for me, i want to recommend you not to make use of $.ajax in angular js its a jquery function; i heard $http is faster than $.ajax function.
Hope this works for you if didnot work please inform me
//$scope.tablerows defined outside the function
$scope.tablerows;
module='user';
url=siteurl+"/admin/"+module+"/list";
BlockUi();
// $http is ajax call in angular js which is equivalent to $.ajax();
$http({
url : url,
method : "GET",
data : "",
headers : { 'Content-Type':undefined,
'Access-Control-Allow-Origin' : '*',
'Access-Control-Allow-Methods' : 'POST, GET, OPTIONS, PUT',
}
//responseText is the output of success call
}).then(function(responseText){
// assigning the response text on the variable
$scope.totaltablerows=responseText.data.response_data;
$scope.tablerows=$scope.totaltablerows;
UnblockUi();
},function(error){
//alert(JSON.stringify(error));
UnblockUi();
UnknownError(JSON.stringify(error));
});

web api 2 post with parameter - must use json.stringyfi

I'm using angularjs and I'm trying to make a HttpPost call to my web api.
My api method:
[HttpPost]
[Route("authentication/getkey")]
public IHttpActionResult GetKey([FromBody]string password) {
//Do stuff
}
my call:
service.getKey = function (password) {
return $http.post('api/authentication/getkey', JSON.stringify(password))
.then(function(result) {
return result.data;
});
}
Now this works fine, but do I really need to use JSON.stringify? I tried sending it like below, but all of them get password = null. Do I have to use JSON.stringify or am I doing it wrong in my other examples?
//Doesnt work
service.getKey = function (password) {
return $http.post('api/authentication/getkey', password)
.then(function(result) {
return result.data;
});
}
//Doesnt work
service.getKey = function (password) {
return $http.post('api/authentication/getkey', {password})
.then(function(result) {
return result.data;
});
}
If you don't want to use JSON.stringify, the other option will be to send the data as application/x-www-form-urlencoded as pointed in other answer as well. This way you are sending the data as form data. I'm not sure about the syntax of the $http.post Shortcut method but the idea is the same.
service.getKey = function (password) {
$http({
method: 'POST',
url: 'api/authentication/getkey',
data: $.param({ '': password }),
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
.then(function(result) {
return result.data;
});
From Microsoft's Web API official documentation about Parameter Binding in ASP.NET Web API:
When a parameter has [FromBody], Web API uses the Content-Type header to select a formatter. In this example, the content type is "application/json" and the request body is a raw JSON string (not a JSON object).
Angular $http service sends Content-Type: application/json as header by default in POST requests, as you can see from the official docs, so Web API is trying to bind your request body using his JsonFormatter. Because of this you have to provide him a well formatted Json string (not a Json Object with a string inside) to correctly bind his raw string parameter.
As a side note, you could also send a request using application/x-www-form-urlencoded as Content-Type header, but then you will have to format your body as form parameters (using something similar to jQuery $.param( .. ))

Slim, Postman and AngularJs : $app->request->getBody() vs $app->request->post()

I'm a beginner. I've written a test application made of an AngularJs GUI on the client side and a PHP API on the server side.
This is the angular service handling the requests
myApp.factory('Book', ['$resource', 'API_URL', function($resource, API_URL){
return $resource(API_URL + '/books/:bookId', {bookId: '#bookId'}, {
get: { method: 'GET', isArray:true },
update: { method: 'PUT'},
save: { method: 'POST'},
delete: {method:'DELETE'},
});
}]);
When I submit a book from the Angular app I can catch the POST in Slim by using
$post_a = json_decode($app->request->getBody());
//$post_b = $app->request->post(); //this would be empty
When I use Postman and I perform a POST I can catch the POST in Slim by using
//$post_a = json_decode($app->request->getBody()); // this would be empty
$post_b = $app->request->post();
I don't get why there is this difference. Could you please explain?
Am I not meant to catch the post just with $app->request->post(); in both the cases? Why the post coming from Angular can be caught only with $app->request->getBody()?
The $app->request->post() method retrieves key/value data submitted in a application/x-www-form-urlencoded request. If the request uses a different content-type (e.g. application/json), you can retrieve the raw request body with the $app->request->getBody() method and decode it as necessary. Let me know if you have further questions.
You could still use
$post_b = $app->request->post()
in Slim.
As long as you call this REST service from html form (AngularJS) by passing the data as form value formatted instead of as JSON.
If in AngularJS you have the data in JSON format, you have to translate it first into form. Below is the example how to invoke this REST service:
Object.toparams = function ObjecttoParams(obj) {
var p = [];
for (var key in obj) {
p.push(key + '=' + encodeURIComponent(obj[key]));
}
return p.join('&');
};
$http({
method: 'POST',
url: url,
data: Object.toparams(myobject),
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
})
myobject is the data in JSON format that is going to be created
Thanks Josh..Your answers works for me.
Steps to follow:
1.You need to send request in json format under raw tab like this:
{"username":"admin","password":"admin"}
2.You need to set Content-Type to application/json in the headers.
That's it and it will work.

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.

Angular $resource PUT method, can't make it work

I use a REST api and I'd like to update on of my project objects with a PUT request. The request is supported in the API, and I'm trying to use $resource to PUT the data, but it doesn't seem to work. Here is what I do :
var projectResource = $resource('/api/projects/' + projectId, {update: {method: "PUT"}});
$scope.editProject = function(editedProject) {
projectResource.$update(editedProject);
}
Where editedProject is the project with the new values, filled by a form in a webpage. I know there is something wrong in my projectResource declaration, but I don't find what. Help !
Try this:
$resource('/api/projects', { id: projectId }, {
update: { method: 'PUT' }
});
$resource cannot make 'PUT' method, cuz of No 'Access-Control-Allow-Origin'. you can only found the 'OPTIONS' in the networks.In this case, you need to create your PUT call:
var data = $resource('someURL', { jobId: '#jobId'}, { 'update': { method:'PUT' }});
data.update(objectYouWannaUpdate);

Resources