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
Related
Learning Angular. Working with 1.6.6 right now.
In my initial stab, I put all my $http requests into my controller, so I'm trying to pull that out of the controller and into a factory for more reusable code. I think that I am missing something related to Promise or injection, but the data from my $http call is not being bound to $scope correctly.
I've been following along this guide.
I have a template that's begin loaded from the controller (the template is loading fine):
<form ng-init="getAllRegions()" ng-submit="getRandomTown()">
<h3>Generate Random Town</h3>
<div class="form-group-row">
<label for="selectRegion">Select Region:</label>
<select name="nameEntity"
id="selectRegion"
ng-model="guidEntity"
ng-options="item.guidEntity as item.nameEntity for item in regions">
<option value="" ng-if="!guidEntity"></option>
</select>
</div>
</form>
The ng-init function is being called, and passes through the controller and the service. In chrome inspector I can see that data is pulling through correctly, but I'm new to working with Promises, so I'm losing something along the way. This was all working as expected when the $http call was right in the controller and the data was being bound to $scope in the controller.
The controller:
angular.
module('randomTown.controller', []).
component('randomTownGenerator', {
templateUrl: 'js/components/randomTownGenerator/randomTownGenerator.tpl.html'
}).
controller('RandomTownCtrl',
function($scope, randomTownFactory) {
$scope.data = {};
$scope.getAllRegions = function () {
$scope.regions = randomTownFactory.getAllDBRegions();
}
}
);
The service:
angular.
module('randomTown.service', []).
factory('randomTownFactory', function ($q, $http) {
var service = {};
service.getAllDBRegions = function() {
var deferred = $q.defer();
$http({
method: 'GET',
url: '/all-regions'
}).then(function success(data) {
deferred.resolve(data);
}), function error(response) {
deferred.reject('There was an error');
}
return deferred.promise;
}
return service;
});
There is no need to manufacture a promise with $q.defer. Simply return the $http promise:
app.factory('randomTownFactory', function ($q, $http) {
var service = {};
service.getAllDBRegions = function() {
̶v̶a̶r̶ ̶d̶e̶f̶e̶r̶r̶e̶d̶ ̶=̶ ̶$̶q̶.̶d̶e̶f̶e̶r̶(̶)̶;̶
̲r̲e̲t̲u̲r̲n̲ $http({
method: 'GET',
url: '/all-regions'
}).then(function success( ̶d̶a̶t̶a̶ response) {
̶d̶e̶f̶e̶r̶r̶e̶d̶.̶r̶e̶s̶o̶l̶v̶e̶(̶d̶a̶t̶a̶)̶;̶
return response.data;
}),̶ ̶f̶u̶n̶c̶t̶i̶o̶n̶ ̶e̶r̶r̶o̶r̶(̶r̶e̶s̶p̶o̶n̶s̶e̶)̶ ̶{̶
̶d̶e̶f̶e̶r̶r̶e̶d̶.̶r̶e̶j̶e̶c̶t̶(̶'̶T̶h̶e̶r̶e̶ ̶w̶a̶s̶ ̶a̶n̶ ̶e̶r̶r̶o̶r̶'̶)̶;̶
̶}̶
̶r̶e̶t̶u̶r̶n̶ ̶d̶e̶f̶e̶r̶r̶e̶d̶.̶p̶r̶o̶m̶i̶s̶e̶;̶,
}
return service;
});
Also notice that the success handler does not reveal the data. It reveals a response object of which data is one of the properties.
The controller:
app.controller('RandomTownCtrl',
function($scope, randomTownFactory) {
$scope.getAllRegions = function () {
var promise = randomTownFactory.getAllDBRegions();
promise.then(function(data) {
$scope.regions = data;
}).catch(function(errorResponse) {
console.log("ERROR", errorResponse.status)
});
}
}
);
For more information, see
AngularJS $http service API Reference
You're Missing the Point of Promises
Try this:
$scope.getAllRegions = function () {
randomTownFactory.getAllDBRegions()
.then((regions) => {$scope.regions = regions});
}
Why: because etAllDBRegions returns a promise, so you have to use then property to get the result
I am new in angular $q service.I'm using $http with angular $q service for implementing asynchronous requests. Here in below is my codes which I can't get the result of backend api. (json)
Services.js :
.service('httpService', function($q, $http, $timeout) {
var asyncRequest = function(url) {
return $http.get(url)
.then(function(response) {
//res is the index of an array in php, which will be encoded.
return response.res;
}, function(response) {
// something went wrong
return $q.reject(response.res);
});
};
return {
asyncRequest : asyncRequest
};
});
Controller.js :
var result = httpService.test(url)
.then(function(data) {
// Line below gives me "undefined"
console.log(data);
}, function(error) {
alert("Error...!");
});
The mentioned line, gives me undefined. (Of course, I can write console.log(data) in main function, But it's not a good practice, because I want to return result to controller)
About my implementation of $q service, is there any easier way?
Any idea would be greatly appreciated.
You should not use $q in this instance, as $http already returns a promise. Using to 2 together in inefficient. ($q is of use if you are using a non-angular async function, such as a Geo lookup).
Services.js :
.service('httpService', function($http, $timeout) {
var asyncRequest = function(url) {
return $http.get(url)
};
return {
asyncRequest : asyncRequest
};
});
Controller.js :
var result = httpService.asyncRequest(url)
.then(function(res) {
console.log(res.data);
}, function(error) {
alert("Error...!");
});
First thing is that you are using factory style instead of service. service is just a function where methods are defined on this reference .
I think you don't need to use .then in service just return the promise returned by $http
app.service('httpService', function($q, $http, $timeout) {
this.asyncRequest = function(url) {
return $http.get(url);
};
});
And in controller
var result = httpService.test(url)
.then(function(res) {
// Line below gives me "undefined"
console.log(res.data);
}, function(error) {
alert("Error...!");
});
I think you are using the syntax for at factory on your service.
.service('httpService', function($q, $http, $timeout) {
this.asyncRequest = function(url) {};
});
or
.factory('httpService', function($q, $http, $timeout) {
return {asyncRequest: function(url) {}};
});
The response is already rejected in the mentioned line. You don't need to reject anything else. So you don't need to $q.
First you already return a promise. You can handle it in the controller with adding success() and error() delegates of the $http promise.
Second, this is async operation. And you can't return a response from the success callback like jQuery.ajax(). This is not synch call, this is asynch call and you have to use callbacks. Your mistake is here. Just return promise and handle it in controller when the response will has been resolved or rejected.
So your controller code can be like this:
httpService.asyncRequest({
...
}).success(function(successfulResponse) {
...
}).error(function(failedResponse) {
...
});
.service('httpService', function($q, $http, $timeout) {
var asyncRequest = function(url) {
var defer = $q.defer();
return $http.get(url)
.then(function(response) {
//res is the index of an array in php, which will be encoded.
defer.resolve(response);
}, function(response) {
// something went wrong
defer.reject(response.res);
});
return defer.promise;
};
return {
asyncRequest : asyncRequest
};
});
you should return promise from your object like this
I created a service that fetches data from local json and use it in a controller to display it in browser. All are working fine. here is my code:
JS Code:
var myApp = angular.module("myApp", ['ngRoute']);
myApp.service("dataService", function($http, $q){
var deferred = $q.defer();
$http.get('json/link.json').then(function(data){
deferred.resolve(data);
});
this.getData = function(){
return deferred.promise;
}
})
.controller("linkCtrl", function($scope, dataService) {
var promise = dataService.getData();
promise.then(function(data) {
$scope.links = data.data;
});
});
Now, i have another json link (for eg.: json/link2.json ) and i want to perform the same function. Is there any way to use the "dataService" service ( like changing the link ).
I don't want to re-create a new service which does the same function. Any idea to re-use the Service for different json data ?
Thanks in Advance
Just create a method you can pass url to:
myApp.service("dataService", function($http){
this.getData = function(url){
return $http.get(url); // this returns a promise
};
})
Use it like this:
.controller("linkCtrl", function($scope, dataService) {
var promise1 = dataService.getData('json/link.json');
promise1.then(function(data) {
$scope.links = data.data;
});
var promise2 = dataService.getData('json/link2.json');
promise2.then(function(data) {
$scope.links2 = data.data;
});
});
Try something like this
myApp.service("dataService", function($http){
this.getData = function(link,callback){
$http.get(link).then(function(data){
if(callback)
callback(data);
});
});
myApp.controller("linkCtrl", function($scope, dataService) {
dataService.getData('json/link.json', function(data){
$scope.links = data.data;
});
});
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 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;
});
});