I am new to learning angular and having trouble understand some of the basics.
I have my controller line shown below:
$scope.test = fileLoader.loadFile();
And my factory service shown below:
angular.module('myWellnessTrackerApp')
.factory('fileLoader', function($http) {
return{
loadfile : function(fileLoc){
$http.get('data/sideEffects.json').success(function(data) {
// you can do some processing here
return data;
});
}
};
});
Which throws an error. But when my controller line is
$scope.test = fileLoader.data;
And my service is
angular.module('myWellnessTrackerApp')
.factory('fileLoader', function($http) {
var obj = {content:null};
$http.get('data/sideEffects.json').success(function(data) {
// you can do some processing here
obj.content = data;
});
return obj;
});
Which i don't understand and I would like to be able to understand how to make services in particularly a HTTP service wrapper for requesting a page or local file and having it returned.
Thanks
You can't just do
$scope.test = fileLoader.loadFile();
loadFile is an async call, and you can't return from that! You can use .then to continue the promise pattern. Your factory would change to:
loadFile : function(fileLoc){
return $http.get('data/sideEffects.json').then(function(result) {
// you can do some processing here
return result.data;
});
}
And your controller:
fileLoader.loadFile().then(function(data) {
$scope.test = data;
});
Related
I'm fairly new to AngularJS and have just begun to grasp many of the concepts I especially like the MVC design pattern. But I am having a difficult time implementing the Service layer in my application.
What I am finding is that after my Controller calls a method within the service, it continues with code execution before the service returns the data; so that by the time the service does return the data, it isn't of any use to the controller.
To give a better example of what I'm saying, here is the code:
var InsightApp = angular.module('InsightApp', ['chart.js']);
// Module declaration with factory containing the service
InsightApp.factory("DataService", function ($http) {
return {
GetChartSelections: function () {
return $http.get('Home/GetSalesData')
.then(function (result) {
return result.data;
});
}
};
});
InsightApp.controller("ChartSelectionController", GetAvailableCharts);
// 2nd Controller calls the Service
InsightApp.controller("DataController", function($scope, $http, DataService){
var response = DataService.GetChartSelections();
// This method is executed before the service returns the data
function workWithData(response){
// Do Something with Data
}
}
All the examples I've found seem to be constructed as I have here or some slight variation; so I am not certain what I should be doing to ensure asynchronous execution.
In the Javascript world, I'd move the service to the inside of the Controller to make certain it executes async; but I don't how to make that happen in Angular. Also, it would be counter intuitive against the angular injection to do that anyway.
So what is the proper way to do this?
http return a promise not the data, so in your factory your returning the $http promise and can use it like a promise with then, catch, finally method.
see: http://blog.ninja-squad.com/2015/05/28/angularjs-promises/
InsightApp.controller("DataController", function($scope, $http, DataService){
var response = DataService.GetChartSelections()
.then(function(res) {
// execute when you have the data
})
.catch(function(err) {
// execute if you have an error in your http call
});
EDIT pass params to model service:
InsightApp.factory("DataService", function ($http) {
return {
GetChartSelections: function (yourParameter) {
console.log(yourParameter);
return $http.get('Home/GetSalesData')
.then(function (result) {
return result.data;
});
}
};
});
and then :
InsightApp.controller("DataController", function($scope, $http, DataService){
var response = DataService.GetChartSelections('only pie one')
.then(function(res) {
// execute when you have the data
})
.catch(function(err) {
// execute if you have an error in your http call
});
You should proceed like this :
DataService.GetChartSelections().then(function (data) {
workWithData(data);
}
Actually $http.get returns a Promise. You can call the method then to handle the success or failure of your Promise
Should it not be like this, when your $http returns a promise or you pass a callback.
With passing callback as a param.
InsightApp.factory("DataService", function ($http) {
return {
GetChartSelections: function (workWithData) {
return $http.get('Home/GetSalesData')
.then(function (result) {
workWithData(result.data);
});
}
};
});
Controller code:
InsightApp.controller("DataController", function($scope, $http, DataService){
var response = DataService.GetChartSelections(workWithData);
// This method is executed before the service returns the data
function workWithData(response){
// Do Something with Data
}
}
Or use then or success:
var response = DataService.GetChartSelections().then(function(res){
//you have your response here... which you can pass to workWithData
});
Return the promise to the controller, dont resolve it in the factory
var InsightApp = angular.module('InsightApp', ['chart.js']);
// Module declaration with factory containing the service
InsightApp.factory("DataService", function ($http) {
return {
GetChartSelections: function () {
return $http.get('Home/GetSalesData');
}
};
});
In the controller,
var successCallBk =function (response){
// Do Something with Data
};
var errorCallBK =function (response){
// Error Module
};
var response = DataService.GetChartSelections().then(successCallBk,errorCallBK);
All server data accesses in my page are performed by my RequestFactory provider.
(The RequestFactory uses $http to perform the actual server calls.)
My controller scope has a reference to the list of data returned from the RequestFactory.
My question is that since the RequestFactory calls are asynchronous, and the RequestFactory does not (and should not) have access to the controller scope, what is the proper way for the RequestFactory to hand off the data to the controller?
var requestFactory = {};
angular.module("myApp").factory("RequestFactory", function($http) {
requestFactory.fetch = function() {
$http.get(url).
success(function(data) {
controller.setData(data)
}).
error(function(data, status) {
console.info("fetch Failed. Error code: " + status + " Url:" + url);
}).finally(function() {
controller.setSubmitting(false);
});
};
return requestFactory;
});
You should return the promise from you factory. See below snippet.
.factory("RequestFactory", function($http) {
return {
fetch : function() {
return $http.get(url).then(function(result) {
return result.data;
});
}
}
});
In your controller you should use like
.controller('MainCtrl', function($scope, RequestFactory) {
RequestFactory.fetch().then(function(data)
$scope.foo = data;
});
});
You can do the following :
Service
(function(){
function Service($http){
function get(){
//We return a promise
return $http.get('path_to_url');
}
var factory = {
get: get
};
return factory;
}
angular
.module('app')
.factory('Request', Service);
})();
Controller
(function(){
function Controller($scope, $q, Request) {
var defer = $q.defer();
//Call our get method from the Request Factory
Request.get().then(function(response){
//When we get the response, resolve the data
defer.resolve(response.data);
});
//When the data is set, we can resolve the promise
defer.promise.then(function(data){
console.log(data);
});
}
angular
.module('app', [])
.controller('ctrl', Controller);
})();
As you know, $http service return promise, so after that, you can easily combining them.
I can see my json data in the console and I want to view it on html page after clickbutton function. From my understaning I can either do a promise ($q) or then with http or ngResource. First I want to do http then migrate to ngResource. For some reason my scope is still undefined. Maybe it's a ng-init or ng-repeat I'm missing? Any ideas?
var app = angular.module('myApp', []);
app.factory('httpq', function($http, $q) {
return {
get: function() {
var deferred = $q.defer();
$http.get.apply(null, arguments)
.success(deferred.resolve)
.error(deferred.resolve);
return deferred.promise;
}
}
});
app.controller('myController', function($scope, httpq) {
httpq.get('http://localhost:8080/states')
.then(function(data) {
$scope.returnedData = data;
})
$scope.clickButton = function() {
$scope.returnedData;
}
});
view
<div data-ng-controller="myController">
<button data-ng-click="clickButton()">Get Data From Server</button>
<p>JSON Data : {{returnedData}}</p>
</div>
Use Ajax call
Service:
var demoService = angular.module('demoService', [])
.service('myService',['$http', function($http) {
this.getdata = function(entity){
var promise = $http({
method : 'POST',
url : 'services/entity/add',
data : entity,
headers : {
'Content-Type' : 'application/json'
},
cache : false
}).then(function (response) {
return response;
});
return promise;
};
}]);
Controller :
var demoService = angular.module('demoService', [])
.controller('myctr',['$scope','myService',function($scope,myService){
myService.getdata().then(function(response){
//Success
},function(response){
//Error
});
}]);
now you can see your json in controller success
$http itself is a promise, no need to create a new promise. Just return the $http.get wihoit the success written there and right the sucess fn in the controller itself. So your code will look like this:
app.factory('httpq', function($http) {
return {
get: function() {
return $http.get.apply(null, arguments);
}
}
});
Your controller:
app.controller('myController', function($scope, httpq) {
httpq.get('http://localhost:8080/states').then(function(data) {
$scope.returnedData = data;
})
$scope.clickButton = function() {
$scope.returnedData;
}
});
use
$scope.returnedData=JSON.parse(data);
It will give you values in JSON format
I have not worked with promise. But your factory code seems to be ok.
In controller declare your object first.
If it's just object declare it as
$scope.returnedData = {};
If it's array, declare it as
$scope.returnedData = [];
The the object will not be undefined and changes will affect in HTML
I am very new to angularjs and am having a hard time trying to figure out this issue.
Basically, we are using a factory to request data for our application. When the factory returns a promise, we were hoping that the data inside the returned promise that was defined in our scope, would be able to be used, but it is only returning as text on the page.
For example: We have defined $scope.name in our controller:
app.controller('AccountController',function($scope,Account) {
$scope.name = 'Abby';
$scope.news = [];
Account.getSnapshot().success(function(data) {
$scope.news.push(data);
});
});
so the factory (getSnapshot) will return something like "Hello {{name}}" from an $http request as follows:
app.factory('Account',function($http) {
return {
getSnapshot : function() {
return $http.get('data.php');
}
}
});
Is it possible to allow the factory to access /use {{name}} from the $scope?
You will need to use internal Angular $interpolate service:
app.controller('AccountController', function($scope, $interpolate, Account) {
$scope.name = 'Abby';
$scope.news = [];
Account.getSnapshot().success(function(data) {
var text = $interpolate(data)($scope);
$scope.news.push(text);
});
});
Use $q and promises thanks to #dfsq's answer on my post similar to this. Works perfectly.
Here's a plunker.
// Factory method.
app.factory('Account', function($http, $q) {
var data;
return {
getSnapshot: function() {
return data ? $q.when(data) : $http.get('data.json').then(function(response) {
data = response.data;
return data;
})
}
}
});
// Controller method.
app.controller('AccountController', function($scope, Account) {
$scope.name = 'Abby';
$scope.news = [];
Account.getSnapshot().then(function(data) {
$scope.news = data;
});
});
I have an Angular service that uses $http to get a json file.
App.factory('jsonFile', function($http) {
var promise;
var jsondata = {
get: function() {
if ( !promise ) {
var promise = $http.get('src/app_preprocess/data_json.js').success(function(response) {
return response.data;
});
return promise;
}
}
};
return jsondata;
});
And a controller
App.controller('firstCtrl', function (jsonFile , $scope) {
jsonFile.get().then(function(d) {
$scope.header = d.data.PACKAGE.ITEM[0]
})
});
This works well.
My question is why can I not add the outcome of the http to a variable instead of the scope like so...?
App.controller('firstCtrl', function (jsonFile , $scope) {
var output;
output = jsonFile.get().then(function(d) {
return d.data.PACKAGE.ITEM
});
$scope.header = output[0];
});
Because jsonFile returns a promise and you try to use output before it returns.. only inside the then clause you can be assured the promise would return in the expected timing. outside of it - you can't now due to the async nature of http calls.
You can read more about promises in angular here