Ionic/Angular js Parsing JSON data from server - angularjs

How to parse JSON object from server using Ionic/Angular js? This is work for me when loading json from /js folder:
var rssApp = angular.module('myApp', []);
rssApp.controller('datas', ['$scope', '$http', function($scope,$http) {
$http.get("js/data.json") // <=== this
.then(function (response)
{
$scope.dat = response;
});
}]);
but when i load json from webserver,i got blank, this is my code :
var rssApp = angular.module('myApp', []);
rssApp.controller('datas', ['$scope', '$http', function($scope,$http) {
$http.get("http://localhost/data.json") //<== this
.then(function (response)
{
$scope.dat = response;
});
}]);
Thanks for your help..

Analyzing what you have done so far, i suppose your data is being returned as an array from the webserver since you are getting blank with your code. So, you should assign the response[0] to $scope.dat.
var rssApp = angular.module('myApp', []);
rssApp.controller('datas', ['$scope', '$http', function($scope,$http) {
$http.get("http://localhost/data.json") //<== this
.then(function (response)
{
$scope.dat = response[0];
});
}]);

First
Angular's $http promise response contains a few properties.
The data returned from the server would be in the data property.
From the Angular docs:
The response object has these properties:
data – {string|Object} – The response body transformed with the
`transform functions.
status – {number} – HTTP status code of the response.
headers – {function([headerName])} – Header getter function.
config – {Object} – The configuration object that was used to generate the request.
statusText – {string} – HTTP status text of the response.
Also you want to make sure that the endpoint is pointing at the correct resource.
I.e if data.json is inside your application file, then the path would be path/to/data.json. This should be easy to identify, because you'll get a 404 status code with your response object.
Solution
So you might want to do something like:
var endpoint = "path/to/data.json";
$http.get(endpoint).then(function (response) {
$scope.dat = response.data;
});
One more thing
Also, if in doubt user console.debug(response); which will allow you to inspect the response object.

Related

Undefined $http data when resolved with `.then` method

I used the console log which returned the array of data fetched from the server, but when I call the scope on the html I get an undefined error on the console.
app.service('blogpostservice', ['$http', function ($http) {
this.getMoreData = function (pagecount) {
return $http.get('/api/posts/' + pagecount);
}
}]);
app.controller('MainController', ['$scope', 'blogpostservice',
function ($scope, blogpostservice) {
$scope.pagec = 1;
this.getMoreData = function () {
blogpostservice.getMoreData($scope.pagec).then(function (data) {
$scope.posts = data;
console.log($scope.posts);
})
}
this.getMoreData();
}]);
HTML
<h1>{{pagec}}</h1>
<h1>{{posts[1].Title}}</h1>
<div id="posts" class="grid" ng-repeat="post in posts">
<div class=" grid-item">
<div class="blog-post">
<img src="https://placeimg.com/400/400/bbc" alt="">
<h3>{{post.Title}}</h3>
<img ng-src="{{post.Image}}" alt="">
</div>
</div>
</div>
The .then method of an $http promise returns a response object, of which data is one of several properties:
app.service('blogpostservice', ['$http', function ($http) {
this.getMoreData = function (pagecount) {
return $http.get('/api/posts/' + pagecount);
}
}]);
app.controller('MainController', ['$scope', 'blogpostservice',
function ($scope, blogpostservice) {
$scope.pagec = 1;
this.getMoreData = function () {
blogpostservice.getMoreData($scope.pagec)
̶.̶t̶h̶e̶n̶(̶f̶u̶n̶c̶t̶i̶o̶n̶ ̶(̶d̶a̶t̶a̶)̶ ̶{̶
.then(function (response) {
͟v͟a͟r͟ ͟d͟a͟t͟a͟ ͟=͟ ͟r͟e͟s͟p͟o͟n͟s͟e͟.͟d͟a͟t͟a͟;͟
$scope.posts = data;
console.log($scope.posts);
})
.catch(function(response) {
console.log("Error: ", response.status);
throw response;
});
};
this.getMoreData();
}
]);
Also be sure to add a .catch handler to log rejected http requests.
For more information, see AngularJS $http Service API Reference.
UPDATE
i read the doc but connecting to the subject the main problem i made is calling it a data instead of a response on the function right?
The main problem is that the http promise does not resolve data. It resolves a response object. Data is only one of the properties of the response object:
$http(...)
.then(function onSuccess(response) {
// Handle success
var data = response.data;
var status = response.status;
var statusText = response.statusText;
var headers = response.headers;
var config = response.config;
...
})
.catch(function onError(response) {
// Handle error
var data = response.data;
var status = response.status;
var statusText = response.statusText;
var headers = response.headers;
var config = response.config;
...
});
From the Docs:
The response object has these properties:
data – {string|Object} – The response body transformed with the transform functions.
status – {number} – HTTP status code of the response.
headers – {function([headerName])} – Header getter function.
config – {Object} – The configuration object that was used to generate the request.
statusText – {string} – HTTP status text of the response.
xhrStatus – {string} – Status of the XMLHttpRequest (complete, error, timeout or abort).
A response status code between 200 and 299 is considered a success status and will result in the success callback being called. Any response status code outside of that range is considered an error status and will result in the error callback being called. Also, status codes less than -1 are normalized to zero. -1 usually means the request was aborted, e.g. using a config.timeout. Note that if the response is a redirect, XMLHttpRequest will transparently follow it, meaning that the outcome (success or error) will be determined by the final response status code.
— AngularJS $http Service API Reference.
Also note that a status of -1 usually is a symptom of a CORS problem. The request being blocked because of a violation of Same Origin Policy.
Rewrite the getMoreData function by using a callback.
See the code sample below
app.service('blogpostservice', ['$http', function ($http) {
this.getMoreData = function (pagecount,callback) {
var result = $http.get('/api/posts/' + pagecount);
if(callback){
callback(result);
}
}
}]);
In essence since you do not know exactly when the getMoreData function will return a value from the http get method you pass the returned data of the http get into a callback function. You then utilize the data from the http get by implementing the callback method in your maincontroller like below:
app.controller('MainController', ['$scope', 'blogpostservice',
function ($scope, blogpostservice) {
$scope.pagec = 1;
this.getMoreData = function () {
blogpostservice.getMoreData($scope.pagec,function(data){ $scope.posts = data; console.log($scope.posts); })
}
this.getMoreData();
}]);
You also need to ensure you that an array is returned from $scope.posts.
Note that in your html you are interpolating {{post}} instead of {{posts}}

Getting error when trying get JSON from remote url

I'm trying load this json file from remote url. In the beginning I was using $http.get function, but I was getting the next error message:
CORS 'Access-Control-Allow-Origin'
Now I am using JSONP, but nothing happens.
service.js file:
angular.module("elcomaApp").factory('ElcomaService', ['$http', function($http){
return $http({
method: 'JSONP',
url: 'http://vagalumewifi.com.br/timeline.json'
}).success(function(response){
return response.data;
}).error(function(err){
return err;
});
}]);
controller.js file:
angular.module("elcomaApp", []).controller('MainController', ['$scope', 'ElcomaService', function($scope, ElcomaService){
$scope.name = 'Natanael Santos';
console.log($scope.name);
ElcomaService.success(function(data){
$scope.elcomaData = JSON.parse(data);
var i = 0;
for (x in $scope.elcomaData){
console.log(i);
i++;
console.log(x.date);
}
}).error(function(data){
console.log(data);
});
}]);
app.js file:
var app = angular.module("elcomaApp", ['ngMaterial', 'ngRoute']);
I already hava read a lot of articles on stackoverflow, but no one work for me.
I'd suggest using $http.jsonp(url) method:
angular.module("elcomaApp").factory('ElcomaService', ['$http', function($http) {
$http.jsonp('http://vagalumewifi.com.br/timeline.json')
.success(function(data) {
console.log(data); // you can't `return` here...
}).error(function(err){
console.err(err);
});
}]);
Note: be warned that you can't expect that return in an async method has the same behavior as in a sync environment... :-)
Your original error is your clue. The endpoint server won't allow access from another domain.
CORS: Cross Origin Requests
You need to allow access on the endpoint server for the type of HTTP method you want to use (i.e. GET, POST, HEAD, ...) Additionally depending on what you're doing you may need to allow for an OPTIONS request, see Preflighted Requests in the MDN documentation above.
If you don't have access to that server you may need to do a work around by making $http call a script on your server that will fetch the file for you. I've done this before using PHP as a proxy and using PHP's file_get_contents function to grab files from other servers of a different domain.

Retrieving data using $http.post

Hi I want to get data from my json file using post method(which is working 5n with get method)
'use strict';
angular.module('myapp').controller('lastWeekWinners',function($http){
var vm= this;
$http.post('http://localhost:9000/json/sample.json').then(function(data){
vm.winnerData=data.data.data;
},function(error){
console.log(error);
});
});
the about code is give error
which means can't we use post method to get the data
This is how u can use the post method in your controller:
'use strict';
angular.module('myapp').controller('lastWeekWinners', controller){
function controller($scope,fetch){
var vm= this;
vm.show = show;
}
function show() {
return fetch.show()
.then(function successCallback(data){
vm.winnerData = data;
}
}, function errorCallback (response) {
console.log(response.statusText);
});
}
});
and in your service :
angular
.module('service',[])
.service('fetch', Service);
function Service($http) {
var fetch = {
show : show
}
return fetch;
function show() {
return $http.get('http://localhost:9000/json/sample.json')
.then(getShowComplete)
.catch(getShowFailed);
function getShowComplete(response){
return response.data;
}
function getShowFailed(error){
console.log("Error:" + error);
}
}
First of all, the difference between GET/POST:
GET is used for getting data, POST is used for saving (and sometimes updating) data. So if you just want to get the json, use GET.
Regarding the specific problem you have here, if you look carefully, you get a 404 code. that means the route was not found. (You can read more about HTTP status code here: http://www.restapitutorial.com/httpstatuscodes.html)
Not sure what server you're using but usually, you're not only defining a route but also the verb of the route (GET/POST/PUT/DELETE), so if you have a route defined like:
GET /users/
This will only work for GET requests, if you try to post for the same route you'll get 404. You have to define the same route for the POST verb.
You can read more about http verbs here: http://www.restapitutorial.com/lessons/httpmethods.html
To do $http.post you need a back end API(PHP,Node Js etc),that system catch your desired post data and save into the db or JSON(Read/Write Method).
Static JSON data just read only possible not write.
Or used Browser $window.localStorage to save data.

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!

Overriding Angular $http post to extend every post data with additional data

In Yii framework, we have to add a CSRF token to the POST data so that the request can be validated.
The token is generated by PHP and I'm passing the variable like this
angular.module('MyConstant', []).constant("MyConstant",
{'postdata': {'_csrf': 'ABCDEF'}}); //this is written by PHP
var app = angular.module('MyApp', ['MyConstant']);
app.controller('MyCtrl', [
'$scope', '$http', 'MyConstant',
function ($scope, $http, MyConstant) {
}]);
whenever I want to send POST, I have to do something like this.
$http.post(url, angular.extend(MyConstant.postdata, {data: mydata}));
The POST body will be something like this
{"_csrf": "ABCDEF", "data": "bla bla bla"}
I'm just curious if there is a "Angular way" to override the $http.post to automatically append the data to avoid code duplication like angular.extend(ViewConstants.postdata above.
UPDATE
Thanks to #GregL for the pointers. I can do it like this using interceptors
app.config(['$httpProvider', 'MyConstant',
function ($httpProvider, MyConstant) {
$httpProvider.interceptors.push(function () {
return {
request: function (config) {
if (config.method == "POST"){
config.data = angular.extend(MyConstant.postdata, config.data);
}
return config;
}
};
});
}]);
Yes, you should be able to register an interceptor.
Just add an interceptor for the request method, and check if the config.method === 'POST' and if so, add your constant to the data sent (config.data).

Resources