I wrote a factory to long-poll, with start and stop methods. However, I can't cancel the timer. Any ideas?
app.controller("AuthCtrl", function($scope, $http, $window, User, Poller) {
Poller.start(1, $scope.session.user.user_uuid, function(result) {
User.data.queues.montage_progress = result.field;
if (result.field == 100) {
Poller.stop(); //DOES NOT STOP (see below)
}
});
})
Here is the factory:
app.factory('Poller', function($http, $q, $interval, $window) {
var poll = this;
poll.timer = null;
poll.checkProgress = function(field, user_uuid) {
var deferred = $q.defer();
$http({
method: 'GET',
url: '/api/v1/poll/',
json: true,
params: {
field: field,
user_uuid: user_uuid
}
})
.success(function(data) {
deferred.resolve(data);
}).error(function() {
deferred.reject("Error checking poll");
});
return deferred.promise;
};
poll.start = function(url, user_uuid, callback) {
poll.timer = $interval(function() {
poll.checkProgress(url, user_uuid).then(function(result) {
console.log(result);
callback(result);
}, function(error) {
alert(error);
});
}, 2000);
};
poll.stop = function() {
$interval.cancel(poll.timer);
};
return poll;
});
EDIT:
Changed $window.clearInterval to $interval.cancel(poll.timer); as suggested below. But still can't cancel polling...
You should use the cancel method of $interval, not clearInterval
poll.stop = function() {
$interval.cancel(poll.timer):
};
Related
I am binding translation.
The issue is , some object convert to translated value, while some like mentioned below didn't work. This issue happened only first time when I build project. On refresh it gets fine.
This is not happening to all html objects.
angular.module('App').factory('APILoader', ['localStorageService', '$http', '$q', function (localStorageService, $http, $q) {
var translationAPIUrl = "Translation/Get";
return function (options) {
var deferred = $q.defer();
$http.get(translationAPIUrl, { params: { id: culture } }).success(function (response) {
data = JSON.parse(response.data);
deferred.resolve(data);
}).error(function (data) {
deferred.reject(options.key);
});
return deferred.promise;
};
}]);
Html:
<b> {{('Heading' |translate)}}</b>
I got it.
The issue is with deferred,
It did not resolve properly and get return.
The Key line is:
deferred.promise.then(function () {});
Here is the fixed code:
angular.module('App').factory('APILoader', ['localStorageService', '$http', '$q', function (localStorageService, $http, $q) {
var translationAPIUrl = "Translation/Get";
return function (options) {
var deferred = $q.defer();
$http.get(translationAPIUrl, { params: { id: culture } }).success(function (response) {
data = JSON.parse(response.data);
deferred.resolve(data);
deferred.promise.then(function () {});
});
}).error(function (data) {
deferred.reject(options.key);
});
return deferred.promise;
};
}]);
I need to fill dropdown on view load. But problem is that when i'm trying to fill dropdown it appears blank. I
Controller
app.controller('CurrencyCtrl', ['$scope', 'Currency', '$http', function ($scope, Currency) {
$scope.curencies = [];
Currency.get(function (response) {
angular.forEach(response, function (val, key) {
$scope.currencies.push(val);
});
});
View
<select class="form-control" name="country"
data-ng-model="curencies"
data-ng-options="option.name for option in curencies.value track by curencies.id">
</select>
Resourse
app.factory("Currency", function ($resource) {
return $resource("api/currencies", {}, {
get: {method: "GET", isArray: true}
});
});
Data Factory
var datafactory = angular.module('Currency', ['Currency']);
datafactory.factory('Currency', function ($http, $q) {
return {
//Get Data
getCurrency: function (Date) {
var deferred = $q.defer();
$http({
method: 'GET',
url: 'api/Send_Mail'
}).success(function (data) {
deferred.resolve(data);
}).error(function (response) {
deferred.reject(response);
});
return deferred.promise;
}
}
Inside Controller
$scope.loadstatus++;
Factory.getCurrency().then(function (data) {
$scope.loadstatus++;
//do something
}, function (err) {
$scope.loadstatus--;
alert("Error" + error);
});
You could use loadstatus to controller the page loading
Try this:
Controller
app.controller('CurrencyCtrl', ['$scope', 'Currency', '$http', function ($scope, Currency) {
$scope.curencies = Currency.get();
});
View
<select class="form-control" name="country"
data-ng-model="curencies"
data-ng-options="option.name for option in curencies track by curencies.id">
</select>
Resourse
app.factory("Currency", function($resource, $q) {
return {
get: function() {
var deferred = $q.defer();
$resource("api/currencies").get().$promise.then(function(response) {
var result = [];
angular.forEach(response, function(val, key) {
result.push(val);
});
deferred.resolve(result);
})
return deferred.promise;
}
};
});
I inject this into my controller module:
var services = angular.module('services', []);
services.factory('jsonManager', ['$http', function($http) {
return{
loadData: loadData
}
function loadData(){
$http({
method: 'GET',
url: 'data/2015_data.json'
}).then(function successCallback(response) {
return response.data;
}, function errorCallback(response) {
return response.err;
});
}
}]);
... and it doesn't work! I'm using it on the controller like this, check it out:
var ctrls = angular.module('controllers', ['services']);
ctrls.controller('overviewController', ['jsonManager', '$scope',
function(jsonManager, $scope){
$scope.load = function(){
var datos = jsonManager.loadData();
console.log(datos);
$scope.gastos = datos.gastos.data;
$scope.ganancias = datos.ganancias.data;
}
I omitted some code from my controller; the scope objects work properly. The problem is, that I get an error that tells me that "datos" is undefined at lines 55 and 56. Why does this happen?
The $http service returns a promise, so you need to use then(successCallback, errorCallback) to resolve the promise.
service
var services = angular.module('services', []);
services.factory('jsonManager', ['$http', function($http) {
var loadData = function(){
$http({
method: 'GET',
url: 'data/2015_data.json'
});
return {
loadData: loadData
};
}]);
controller
var ctrls = angular.module('controllers', ['services']);
ctrls.controller('overviewController', ['jsonManager', '$scope', function(jsonManager, $scope){
$scope.load = function(){
var datos = jsonManager.loadData().then(function(res) {
console.log(res.data);
$scope.gastos = res.data.gastos.data;
$scope.ganancias = res.data.ganancias.data;
}, function(err) {
console.log(err);
});
};
}]);
$http is asynchronous and
console.log(datos);
$scope.gastos = datos.gastos.data;
is run before jsonManager.loadData(); return it's value
Use callbacks or a promises
function loadData(callback){
$http({
method: 'GET',
url: 'data/2015_data.json'
}).then(function successCallback(response) {
callback(null, response.data);
}, callback);
}
$scope.load = function(){
var datos = jsonManager.loadData(function(err, datos){
console.log(datos);
$scope.gastos = datos.gastos.data;
$scope.ganancias = datos.ganancias.data;
});
}
It is asynchronous, so one way would be to force it to resolve in $scope.load like this:
$scope.load = function(){
var datos = jsonManager.loadData().then(function(results){return results;});
console.log(datos);
$scope.gastos = datos.gastos.data;
$scope.ganancias = datos.ganancias.data;
I am filling my template named commentRecipe.html with data.
And i can call controller.add(1,2,'comment here') from inside the template.
The item gets updated in the db and returns my new result.
The Question is: How can i update ex mhRecipeId with the retrieved data.
var app = angular.module('myApp');
app.directive('mhCommentRecipe', ['$log', 'commentService', function ($log, commentService) {
var commentController = function () {
var that = this;
that.add = function (commentId, recipeId, commentText) {
if (recipeId && commentText.length > 0) {
var resultObj = commentService.add(commentId, recipeId, commentText);
}
};
}
return {
restrict: 'A',
templateUrl: '/app/templates/commentRecipe.html',
scope: {
mhRecipeId: '=',
mhCommentId: '=',
mhCommentText: '='
},
controller: commentController,
controllerAs: 'controller'
}
}]);
(function () {
app.factory('commentService', [
'$log', 'httpService', function ($log, httpService) {
var baseEndpointPath = '/myRecipes';
return {
add: function (commentId, recipeId, commentText) {
$log.debug(commentId, 'c');
var data = {
commentId,
recipeId,
commentText
}
var promise = httpService.post(baseEndpointPath + '/comment', data);
promise.then(function (response) {
// added
},
function (error) {
$log.error(error);
});
},
remove: function (commentId) {
if (commentId) {
var data = {
commentId,
recipeId,
commentText
}
data.commentId = commentId;
var promise = httpService.post(baseEndpointPath + '/removeComment', data);
promise.then(function (response) {
$log(response, 'removed response');
},
function (error) {
$log.error(error);
});
}
}
};
}
]);
})();
app.factory('httpService', ['$http', '$q',
function ($http, $q) {
return {
get: function (endpoint) {
var deferred = $q.defer();
$http.get(endpoint)
.success(function (response) {
deferred.resolve(response);
})
.error(function () {
deferred.reject('Failed to fetch response from endpoint');
});
return deferred.promise;
},
post: function (endpoint, data, config) {
var deferred = $q.defer();
$http.post(endpoint, data, config)
.success(function (response) {
deferred.resolve(response);
})
.error(function () {
deferred.reject('Failed to post data to endpoint');
});
return deferred.promise;
},
put: function (endpoint, data, config) {
var deferred = $q.defer();
$http.put(endpoint, data, config)
.success(function (response) {
deferred.resolve(response);
})
.error(function () {
deferred.reject('Failed to put data to endpoint');
});
return deferred.promise;
}
};
}]);
You place the values you want to send to the directive into a variable:
// in controller
that.mhRecipeId = whateverValueHere;
that.mhCommentId = whateverValueHere;
that.mhCommentText = 'comment text';
then on the directive in html you would put:
<mh-comment-recipe mh-recipe-id="controller.mhRecipeId" mh-comment-id="controller.mhCommentId" mh-comment-text="controller.mhCommentText"></mh-comment-recipe>
This will pass the variables into the directive for use.
Unless I misunderstood your question :)
Solved the issue and i am quite embarrassed to tell the solution!
In my view i just used ex: mhRecipeId when i should have used the controllers value.
So this is a bit complex, but I'll try to get into it, the best I can. In my config.js, I have:
.run(['$rootScope', '$location', 'UserService', 'CompanyService', function($rootScope, $location, UserService, CompanyService) {
$rootScope.globals = {};
$rootScope.$on('login', function(event, data) {
$rootScope.api_key = data.api_key;
CompanyService.get(data.user.company_id);
});
UserService.checkAuth().then(function(response) {
if(response.data.user) {
// Logged in user
$rootScope.$broadcast('login', response.data);
} else {
UserService.logout();
}
});
}]);
which basically checks to see if a user is logged in. If he is, we find out which user he belongs to with the CompanyService:
angular.module('mean').service('CompanyService', ['$http', '$rootScope', function($http, $rootScope) {
var company = this;
company.company_data = {}
company.getCompany = function() {
return company.company_data;
}
company.get = function (company_id) {
return $http({
url: '/api/v1/company/' + company_id,
method: 'GET',
headers: {
api_key: $rootScope.api_key
}
}).success(function(response) {
if(response.status === 'ok') {
company.company_data = response.company;
}
});
};
}]);
Later on in my code, I have a call that relies on the singleton CompanyService to do an API call:
$scope.index = function() {
LocationService.get(CompanyService.getCompany()._id, $routeParams.location_parent_id).then(function(response) {
if(response.data.status === 'ok') {
$scope.locations = $scope.locations.concat(response.data.locations);
}
});
}
if I refresh the page, however, sometimes this call gets executed before we've put data in the CompanyService singleton. How can I use promises to make sure that the LocationService doesn't happen until after we have data in the CompanyService singleton?
One way to do this is without changing your existing code too much would be to create a promise that is fulfilled when CompanyService has data. Note that this code doesn't deal with errors so that still has to be added...
angular.module('mean').service('CompanyService',
['$http', '$rootScope', '$q', function ($http, $rootScope, $q) {
var company = this;
company.company_data = {}
var initializedDeferred = $q.defer;
company.initialized = initializedDeferred.promise;
company.getCompany = function () {
return company.company_data;
}
company.get = function (company_id) {
return $http({
url: '/api/v1/company/' + company_id,
method: 'GET',
headers: {
api_key: $rootScope.api_key
}
}).success(function (response) {
if (response.status === 'ok') {
company.company_data = response.company;
initializedDeferred.resolve(); // reject promise on error?
}
});
};
}]);
$scope.index = function () {
CompanyService.initialized.then(function () {
LocationService.get(CompanyService.getCompany()._id,
$routeParams.location_parent_id).then(function (response) {
if (response.data.status === 'ok') {
$scope.locations = $scope.locations
.concat(response.data.locations);
}
});
});
}