I have my js for angular to fetch the json service from http and am using the {{post.title}} on my html to get the data and post to my html.
The data is not showing up on html page - using code pen.
var app = angular.module("blogApp", []);
app.controller("mainCtrl", function($scope) {
$scope.posts = [];
let postsUrl ="https://jsonplaceholder.typicode.com/posts"
getPosts().then(posts =>{
$scope.posts = posts.slice(3);
$scope.$apply();
});
function getPosts(){
return fetch(postsUrl).then(res=>res.json());
}
});
I have seen your shared codepen. So Ricky as you are new to angularJS, I would suggest you to read the documentation related to angular 1 from here: Angular JS - Documentation
Now coming to your requirement, you required to call an external API and use the data from the result. For that you have to learn about the $http in angularJS : $http documentation
Coming to the code, angular supports the dependency injection. The code you have shared is a mystery for me like what fetch(postsUrl) function is doing? Where is the declaration?
Cut and short, the implementation should be clear and readable. Here is my refactored one:
var app = angular.module("blogApp", []); //here you defined the ng-app module
//you are initializing a controller, you need to inject $http for calling the API
app.controller("mainCtrl", function($scope, $http) {
//Declaration of the posts object
$scope.posts = [];
//Onetime initialization of the API Endpoint URL
let postsUrl ="https://jsonplaceholder.typicode.com/posts";
//A method for getting the posts
function getPosts(){
//We are calling API endpoint via GET request and waiting for the result which is a promise
//todo: Read about the Promises
//A promise return 2 things either a success or a failure callback, you need to handle both.
//The first one is success and the second one is a failure callback
//So in general the structure is as $http.get(...).then(successCallback, failureCallback)
$http.get(postsUrl).then(function(response){
//In promises you get data in the property data, for a test you can log response like console.log(response)
var data = response.data;
$scope.posts = data; //Storing the data in the posts variable
//Note: you don't need to call the $scope.$apply() because your request is with in the angular digest process.
//All the request which are outside the angular scope required a $apply()
}, function(err){
//log the err response here or show the notification you want to do
});
}
//The final step is to call that function and it is simple
getPosts();
});
Coming to the second part to show the data. You have to use the ng-repeat documentation, it is as ng-repeat="var item in collection track by $index". It's documentation is here ng-repeat
So you html should be in this structure:
<div ng-repeat="var post in posts track by $index">
{{post.userid}}
{{post.id}}
{{post.title}}
{{post.body}}
</div>
Now it is onto you to learn and implement.
Related
I am trying to implement a faceted search based on AngularJS https://github.com/kmaida/angular-faceted-search
As the example is based on a dataset incorporated in the JS, I am trying to load the JSON File remotely. (total noob in angularJS by the way).
In the example, the Controller is defiend as:
myApp.controller('MainCtrl', function($scope, Helpers) {
And there are 2 helpers defined
myApp.factory('Helpers', function() {...
I am trying to inject the $http in a third helper, my code:
,
//below line 30 in https://github.com/kmaida/angular-faceted-search/blob/master/app.js
fetchData: function (){
var resultjson=[]
$http.get('/api/data.json').success(function(data) {
resultjson=data
console.log(data);
});
console.log(resultjson);
return resultjson;
}
The newly defined variable resultjson has a value in the success function, but no value beyond that point.
Any one can help me fetch the data correctly? Appreciate the support.
If you want to receive data from $http, you will have to use promises. Right now, you are returning resultjson before the value has been received from the api end point.
You should return promise, and once the promise is resolved, the value will be in the promise.
Due to the fact, that $http returns promise, you can return it directly, without wrapping it in another promise.
fetchData: function (){
return $http.get('/api/data.json');
}
and you can access the data in your your controller and assign to the scope:
Helpers.fetchData().then(function(data){
$scope.items = data.data;
})
I've been facing a trouble while working with Factory/Service. I've created an AjaxRequests factory for all of my AJAX calls. My factory code is
.factory('AjaxRequests', ['$http', function ($http) {
return {
getCampaignsData: function () {
var campaigns
return $http.get(url).then(function (response) {
campaigns = response.data;
return campaigns;
});
}
}
}])
I've created another service in which I am injecting this factory. My service code
.service('CampaignsService', ['$rootScope', 'AjaxRequests', function ($rootScope, AjaxRequests) {
this.init = function () {
this.camps;
AjaxRequests.getCampaignsData().then(function (response) {
this.camps = response.campaigns;
console.log(this.camps); // It is showing data
})
console.log(this.camps); // But it is not working :(
};
this.init();
}])
And in my controller
.controller('AdvanceSettingsController', ['$scope', 'CampaignsService', function ($scope, CampaignsService) {
$scope.CampaignsService = CampaignsService;
}
])
I've read this article to learn promises but it is not working here. I can directly achieve it in controller and it's been working fine. But it consider as a bad coding standard to make controller thick. But when I use service and factory I stuck. My question is why I am not getting ajax data to use in my whole service ? I need to use CampaignsService.camps in my view template as well as in my whole rest script but every time I get undefined. What is happening here? I've asked the same question before but couldn't get any success. Some one please help me to understand about promises and why I am getting this type of error if I'm working same ? This type of question has already been asked before but it was working in controller. May be I am stuck because I'm using it in a service.
A big thanks in advance.
This is not a bug or some tricky functionality. Just like in any other AJAX implementation, you can only access the response data in AngularJS's $http success method. That's because of the asynchronous nature of Asynchronous JavaScript And XML.
And what you have is working.
.controller('AdvanceSettingsController', ['$scope', 'AjaxRequests', function ($scope, AjaxRequests) {
$scope.camps = [];
AjaxRequests.getCampaignsData().then(function(data) {
$scope.camps = data;
});
}
])
And then bind camps:
<div ng-repeat="camp in camps>{{camp.name}}</div>
What's bad in your implementation is that instead of grouping related stuff in services you are writing a big AjaxRequests service for everything. You should have a CampaignsService that has a getData method and inject that in your controller.
Why is this working? Because $http does a $scope.$apply for you, which triggers a digest cycle after the data is loaded (then) and updates the HTML. So before the then callback that ng-repeat is run with [] and after it it's again run but with data from the response because you are setting $scope.camps = data;.
The reason <div ng-repeat="camp in CampaignsService.camps>{{camp.name}}</div> does not work is because of function variable scoping.
The this reference inside of your then callback is not the same as the this reference outside of it.
This will work and uses the common var self = this trick:
var self = this;
this.camps = [];
this.init = function () {
AjaxRequests.getCampaignsData().then(function (response) {
// here "this" is not the one from outside.
// "self" on the other hand is!
self.camps = response.campaigns;
});
};
I am trying to call a service in angular.js through a controller on load and return a promise. I then expect the promise to be fulfilled and for the DOM to be updated. This is not what happens. To be clear, I am not getting an error. The code is as follows.
app.controller('TutorialController', function ($scope, tutorialService) {
init();
function init() {
$scope.tutorials = tutorialService.getTutorials();
}
});
<div data-ng-repeat="tutorial in tutorials | orderBy:'title'">
<div>{{tutorial.tutorialId}}+' - '+{{tutorial.title + ' - ' + tutorial.description}}</div>
</div>
var url = "http://localhost:8080/tutorial-service/tutorials";
app.service('tutorialService', function ($http, $q) {
this.getTutorials = function () {
var list;
var deffered = $q.defer();
$http({
url:url,
method:'GET'
})
.then(function(data){
list = data.data;
deffered.resolve(list);
console.log(list[0]);
console.log(list[1]);
console.log(list[2]);
});
return deffered.promise;
};
});
Inside of the ".then()" function in the service, I log the results and I am getting what I expected there, it just never updates the DOM. Any and all help would be appreciated.
getTutorials returns promise by itself. So you have to do then() again.
tutorialService.getTutorials().then(function(data){
$scope.tutorials = data;
});
Before that, $http returns a promise with success() and error().
Although you can also use then as well
Since the returned value of calling the $http function is a promise,
you can also use the then method to register callbacks, and these
callbacks will receive a single argument – an object representing the
response.
So you are correct with that.
What is your data coming from the http call look like? Your code works - I created a version of it here http://jsfiddle.net/Cq5sm/ using $timeout.
So if your list looks like:
[{ tutorialId: '1',
title : 'the title',
description: 'the description'
}]
it should work
In newer Angular versions (I think v 1.2 RC3+) you have to configure angular to get the unwrap feature working (DEMO):
var app = angular.module('myapp', []).config(function ($parseProvider) {
$parseProvider.unwrapPromises(true);
});
This allows you to directly assign the promise to the ng-repeat collection.
$scope.tutorials = tutorialService.getTutorials();
Beside that I personally prefer to do the wrapping manually:
tutorialService.getTutorials().then(function(tutorials){
$scope.tutorials = tutorials;
});
I don't know the exact reason why they removed that feature from the default config but it looks like the angular developers prefer the second option too.
I have a factory called "Server" which contains my methods for interaction with the server (get/put/post/delete..). I managed to login and get all data successfully when I had all my code in my controller. Now that I want to separate this code and restructure it a little bit I ran into problems. I can still login and I also get data - but data is just printed; I'm not sure how to access the data in controller? I saw some ".then" instead of ".success" used here and there across the web, but I don't know how exactly.
This is my factory: (included in services.js)
app.factory('Server', ['$http', function($http) {
return {
// this works as it should, login works correctly
login: function(email,pass) {
return $http.get('mywebapiurl/server.php?email='+email+'&password='+pass').success(function(data) {
console.log("\nLOGIN RESPONSE: "+JSON.stringify(data));
if(data.Status !== "OK")
// login fail
console.log("Login FAIL...");
else
// success
console.log("Login OK...");
});
},
// intentional blank data parameter below (server configured this way for testing purposes)
getAllData: function() {
return $http.get('mywebapiurl/server.php?data=').success(function(data) {
console.log("\nDATA FROM SERVER: \n"+data); // here correct data in JSON string format are printed
});
},
};
}]);
This is my controller:
app.controller("MainController", ['$scope', 'Server', function($scope, Server){
Server.login(); // this logins correctly
$scope.data = Server.getAllData(); // here I want to get data returned by the server, now I get http object with all the methods etc etc.
…. continues …
How do I get data that was retrieved with $http within a factory to be accessible in controller? I only have one controller.
Thanks for any help, I'm sure there must be an easy way of doing this. Or am I perhaps taking a wrong way working this out?
EDIT: I also need to be able to call factory functions from views with ng-click for instance. Now I can do this like this:
// this is a method in controller
$scope.updateContacts = function(){
$http.get('mywebapiURL/server.php?mycontacts=').success(function(data) {
$scope.contacts = data;
});
};
and make a call in a view with ng-click="updateContacts()". See how $scope.contacts gets new data in the above function. How am I supposed to do this with .then method?(assigning returned data to variable)
My question asked straight-forwardly:
Lets say I need parts of controller code separated from it (so it doesn't get all messy), like some functions that are available throughout all $scope. What is the best way to accomplish this in AngularJS? Maybe it's not services as I thought …
The trick is to use a promise in your service to proxy the results.
The $http service returns a promise that you can resolve using then with a list or success and error to handle those conditions respectively.
This block of code shows handling the result of the call:
var deferred = $q.defer();
$http.get(productsEndpoint).success(function(result) {
deferred.resolve(result);
}).error(function(result) { deferred.reject(result); });
return deferred.promise;
The code uses the Angular $q service to create a promise. When the $http call is resolved then the promise is used to return information to your controller. The controller handles it like this:
app.controller("myController", ["$scope", "myService", function($scope, myService) {
$scope.data = { status: "Not Loaded." };
myService.getData().then(function(data) { $scope.data = data; });
}]);
(Another function can be passed to then if you want to explicitly handle the rejection).
That closes the loop: a service that uses a promise to return the data, and a controller that calls the service and chains the promise for the result. I have a full fiddle online here: http://jsfiddle.net/HhFwL/
You can change the end point, right now it just points to a generic OData end point to fetch some products data.
More on $http: http://docs.angularjs.org/api/ng.%24http
More on $q: http://docs.angularjs.org/api/ng.%24q
$http.get retuns a HttpPromise Object
Server.getAllData().then(function(results){
$scope.data = results;
})
HTML:
<div class="span10" ng-controller="GroupFieldsCntl" ng-init="init()">
<div ng-repeat="field in fields"></div>
</div>
GroupFieldCntl:
function GroupFieldsCntl($scope) {
$scope.fields = [];
$scope.init = function() {
// Get fields.
$.get(ctx + 'admin/fields/fieldsJSON', function(data) {
for(var i in data) {
$scope.fields.push(data[i]);
}
});
}
}
I'm sure the ajax call get correct response, but the html page doesn't display those data.
Like the commentors here say:
1. Use $http.get instead of $.get. This is Angular's Ajax and you should be using it. [it needs to be injectecd into the controller]
2. If you loop in var i in data you might loop through methods of non-data properties, so as was suggested, use
for (var i in data) {
if data.hasOwnProperty(i)
//do something
}
}
And if you don't think there will be issues with bad data, you can always use the following syntax to have the resolved promise (get request) resolve itself to the $scope variable:
$scope.fields = $http.get(tx + 'admin/fields/fieldsJSON');
When the data arrives fields will automatically contain the JSON response after it was resolved. This is a shortcut which doesn't handle error responses though.
The changes done to data will trigger view changes only if you do it with angular functions or use $apply on other functions. So as the comments suggest you can (should) either use angular's $http service, or call your function inside $apply.