first of all, i'm a noob to AngularJS - hope someone can help with this one. I really don't get it..
I have a AngularJS app, with a "service" that return a promise, that works all well, but the problem is, if my app at the beginning is offline, and afterward gets online, now I want the service promise to refresh.
If my app is online at the beginning, it all works well.
But if it is offline, and later gets online, and the reload button is clicked - the alert("TEST TEST"); never gets executed :(
.service('webService', function ($http, $q, $timeout){
var webservice_url = "http://mywebservice_url";
var deferred = $q.defer();
var service = {};
service.refresh = function() {
$http.get(webservice_url+"?action=get_settings", {timeout: 2000})
.success(function(data) {
deferred.resolve(data);
})
.error(function(err) {
deferred.reject({'error': err});
});
return deferred.promise;
}
this.refresh = function() {
this.promise = service.refresh();
return this.promise;
}
this.promise = service.refresh();
})
.controller('NetworkCtrl', function($scope, $location, $timeout, webService) {
$scope.reloadClick = function(){
webService.refresh().then(function(data) {
alert("TEST TEST");
console.log(data);
});
}
})
I am not 100% positive... cause I can't run your code... but I think that moving line three into the service.refresh method, that should get you closer.
Related
I'm trying to automate an angular app using selenium. Before running the selenium script I would want to wait for the app to completely load. I used the following code to do this, but after the app was updated to a new angular version, I'm not able to get the pending requests using this method.
I tried searching for a solution for a few days, but couldn't find any. Thanks in advance :)
angular.element(document).injector().get('$http').pendingRequests.length.toString();
In the latest Angular, you can access Pending Requests from the built-in HTTP$ directly
Or if you want to wrap it in a service look ref from here/below
angular.module('app', [])
// This service keeps track of pending requests
.service('pendingRequests', function() {
var pending = [];
this.get = function() {
return pending;
};
this.add = function(request) {
pending.push(request);
};
this.remove = function(request) {
pending = _.filter(pending, function(p) {
return p.url !== request;
});
};
this.cancelAll = function() {
angular.forEach(pending, function(p) {
p.canceller.resolve();
});
pending.length = 0;
};
})
// This service wraps $http to make sure pending requests are tracked
.service('httpService', ['$http', '$q', 'pendingRequests', function($http, $q, pendingRequests) {
this.get = function(url) {
var canceller = $q.defer();
pendingRequests.add({
url: url,
canceller: canceller
});
//Request gets cancelled if the timeout-promise is resolved
var requestPromise = $http.get(url, { timeout: canceller.promise });
//Once a request has failed or succeeded, remove it from the pending list
requestPromise.finally(function() {
pendingRequests.remove(url);
});
return requestPromise;
}
}])
I am using the AngularBooter for Angular in my app.
Here is my code:
emp.boot();
emp.services.SocialService = ['$http', '$q', function ($http, $q) {
var deferred = $q.defer();
$http.get('/api/feed').then(function (data) {
deferred.resolve(data);
});
this.getStatuses = function ()
{
return deferred.promise;
}
}];
emp.controllers.StatusesController = ['$scope','SocialService', '$interval', function($scope, SocialService, $interval) {
var statuses = SocialService.getStatuses();
statuses.then(function(data) {
$scope.statuses = data;
console.log($scope.statuses);
});
}];
From what I understand the error: Error: [$injector:unpr] is a sign that the service isn't being registered or implemented correctly, I have tried a few things but keep running into the same problem. Any ideas.
Two problems:
1) You are booting before you register your stuff (at least in the code you provided). Do emp.boot() right at the bottom after everything has been defined.
2) Your service is not returning anything. For instance, if you add return {}; at the very bottom of your service function, it should magically not throw the error anymore, but you probably want to return something more interesting than that.
You can see this in action by uncommenting the line that returns the object and see Angular start working again.
http://codepen.io/alex-wilmer/pen/QbwNGz?editors=101
I imagine you probably want something like this:
emp.services.SocialService = ['$http', '$q', function ($http, $q) {
var deferred = $q.defer();
$http.get('/api/feed').then(function (data) {
deferred.resolve(data);
});
return {
getStatuses = function () { // don't mix brace placement!
return deferred.promise;
}
};
}];
I'm using a service to make user data available to various controllers in my Angular app. I'm stuck trying to figure out how to use the $http service to update a variable local to the service (in my case "this.users"). I've tried with and without promises. The server is responding correctly.
I've read several excellent articles for how to use $http within a service to update the scope of a controller. The best being this one: http://sravi-kiran.blogspot.com/2013/03/MovingAjaxCallsToACustomServiceInAngularJS.html. That does not help me though because it negates the benefits of using a service. Mainly, modifying the scope in one controller does not modify throughout the rest of the app.
Here is what I have thus far.
app.service('UserService', ['$http', function($http) {
this.users = [];
this.load = function() {
var promise = $http.get('users.json')
.success(function(data){
// this.users is undefined here
console.log(this.users);
}
};
promise.then(function() {
// this.users is undefined here
console.log('this.users');
});
}]);
Any help is greatly appreciated. Thank you.
Try using
var users = [];
rather than
this.users = [];
and see what
console.log(users);
outputs in each of those cases.
Your service is oddly defined, but if you have a return in it you can access it from any controller:
app.service('UserService', ['$http', function($http) {
var users = [];
this.load = function() {
var promise = $http.get('users.json')
.success(function(data){
// this.users is undefined here
console.log(users);
users = data.data;
}
};
return {
getUsers: function(){
return users;
}
}
}]);
so in your controller, you can use:
var myUsers = UserService.getUsers();
UPDATE to use a service correctly here, your service should return a promise and the promise should be accessed in the controller: Here's an example from another answer I gave
// your service should return a promise
app.service('PickerService', [$http', function($http) {
return {
getFiles: function(){
return $http.get('files.json'); // this returns a promise, the promise is not executed here
}
}
}]);
then in your controller do this:
PickerService.getFiles().then(function(returnValues){ // the promise is executed here as the return values are here
$scope.myDirectiveData = returnValues.data;
});
this does not have scope anymore where you are trying to use it do this instead:
app.service('UserService', [$http', function($http) {
var users = [];
this.load = function() {
var promise = $http.get('users.json')
.success(function(data){
console.log(users);
}
};
promise.then(function() {
console.log(users);
});
}]);
all local variables to a service should just be vars if you assign them to this as a property than they will be included every time the service is injected into a controller which is bad practice.
I think what your asking for is a solution along the lines of defining your service like this:
angular.module('app')
.service('User', function($http, $q) {
var users = null;
var deferred = $q.defer()
return {
getUsers: function() {
if(users) {
deferred.resolve(users);
} else {
$http.get('users.json');
.success(function(result) {
deferred.resolve(result);
})
.error(function(error) {
deferred.reject(error);
});
}
return deferred.promise;
}
};
});
Then in one Each controller you would have to do this:
angular.module('app')
.controller('ACtrl', function($scope, User) {
User.getUsers().then(function(users) {
// Same object that's in BCtrl
$scope.users = users;
});
});
angular.module('app')
.controller('BCtrl', function($scope, User) {
User.getUsers().then(function(users) {
// Same object that's in ACtrl
$scope.users = users;
});
});
NOTE: Because the deferred.promise the same promise passed to all controllers, executing deferred.resolve(users) in the future will cause all then success callbacks in each of your controllers to be called essentially overwriting the old users list.
All operations on the list will be noticed in all controllers because the users array is a shared object at that point. This will only handle updates to the user list/each individual user on the client side of your application. If you want to persist changes to the server, you're going to have to add other $http methods to your service to handle CRUD operations on a user. This can generally be tricky and I highly advise that you check out ngResource, which takes care of basic RESTful operations
I make an $http call inside a service that is supposed to get data from my server. For some reason I can't get my service to work - nothing happens. I know the server code works because if I place the $http call inside a function within my controller, then it gets the server data as expected. Here is the code I have so far:
app.service('myService', function($q,$compile,$http) {
this.getData = function() {
var deferred = $q.defer();
var promise = $http.get('myfile.php').success(function (data) {
var response = $compile(data)($scope);
deferred.resolve(response);
});
return deferred.promise;
};
});
Also, I know the code that uses this service works because if I do something like the following,
app.service('myService', function() {
this.getData = function() {
return 'TEST';
};
});
then I will see the word "TEST" show up in the div that utilizes this service. I feel like I'm very close, but there is something I am missing. Any ideas on what I'm doing wrong?
UPDATE:
controller: function($scope, $http, $rootScope, myService){
var scope = $rootScope;
scope.viewMyData = function() {
var element = myService.getData();
$('#myDiv').html(element);
}
}
HTML:
<div ng-click="viewMyData()">Click Here</div>
<div id="myDiv"></div>
If I strip the code in myService and simply return TEST (as above), then I will see "TEST" show up in id="myDiv". But for some reason the $http call isn't being triggered.
#tymeJV is right, but here's my attempt to spell out the example better. $http returns a promise interface that allows you to chain callbacks to be executed when the $http response returns. So, in this case, calling myService.getData() can't return the result immediately (it's off getting the data from the server), so you need to give it a function to execute when the server finally responds. So, with promises, you simply attach your callback using the thePromise.then(myCallbackFunc).
Service
app.service('myService', function($q,$compile,$http) {
this.getData = function() {
var promise = $http.get('myfile.php');
promise = promise.then(function (response) {
return response.data;
});
return promise;
};
});
Controller
controller: function($scope, $rootScope, myService){
var scope = $rootScope;
scope.viewMyData = function() {
myService.getData().then(function(data) {
$('#myDiv').html(element);
});
}
}
Use .then in the controller to continue the promise pattern:
myService.getData().then(function(data) {
$('#myDiv').html(data);
});
I am new to Angular JS and really struggling to get data into my controller from javascript remoting. Has anyone done this before?
Visualforce.remoting.Manager.invokeAction('{!$RemoteAction.Forecasting.Users}',
new Object(),function(result, event){
return result
}
);
How on earth do i get the data into the controller :
var forecastingCtrl = function($scope, $q){
$scope.lengths = function(){return '5'};
$scope.users = [];
}
EDIT : Following works fine:
fc.service('Users', function($rootScope, $q) {
this.get = function(){
var deferred = $q.defer();
Visualforce.remoting.Manager.invokeAction('{!$RemoteAction.Forecasting.Users}',new Object(),function(result, event){
if(event) {
$rootScope.$apply(function() {
deferred.resolve(result);
});
} else {
deferred.reject(result);
}
});
return deferred.promise;
}
});
function forecastingCtrl($scope, $q, Users){
$scope.lengths = function(){return '5'};
var promise = Users.get();
promise.then(
function(users){
$scope.users = users;
},
function(reason){
alert('Failed: ' + reason);
}
);
};
I haven't used javascript remoting (sounds interesting) but what you will probably want to do is to encapsulate your visualforce code inside a service, having a method (most likely a promise) to return your data and inject the service into your controller. The upside of this is that you can unit test your controller by injecting a mock or spy of your data service. The pattern would be very much like how you would use angular's $http and $resource services. Hopefully this gets you on the right track.