Error: error:unpr Unknown Provider injected service in controller - javascript

I have no idea what i'm doing wrong, all of my other services work no problem. What i'm attempting to do is upload a photo. Originally the service part of the code was inside the controller, and i refactored it to be a service because I didnt want to write another whole set of code to upload again after editing a photo(This is what service is for right?)
controller:
app.controller('UploadCtrl', ['$scope', '$upload','UploadService',
function($scope, $upload,UploadService) {
$scope.uploads = [];
var photos = $scope.$parent.photos;
for (i = 0; i < 3; i++) {
$scope.uploads[i] = {
id: i+1,
showLink: photos[i].showLink,
showProg: false,
progress: 0,
photoUrl: photos[i].dataUrl
}
}
}
]);
factory:
app.factory('UploadService',['$upload', '$scope', function($upload,$scope){
$scope.onFileSelect = function($files, $_upload) {
for (var i = 0; i < $files.length; i++) {
var $file = $files[i];
//set thumbnail
$scope.dataUrl = null;
if ($file.type.indexOf('image') > -1) {
var fileReader = new FileReader();
fileReader.readAsDataURL($file)
var loadFile = function(fileReader) {
fileReader.onload = function(e) {
// console.log(e.target.result);
$_upload.dataUrl = e.target.result;
$_upload.showLink = false;
$_upload.showProg = true;
}
}(fileReader);
}
$scope.upload = $upload.upload({
url: 'upload_picture',
method: 'POST',
file: $file,
fileFormDataName: 'provider[photo_' + $_upload.id + ']'
}).progress(function(event) {
$_upload.progress = parseInt(100.0 * event.loaded / event.total);
// console.log('percent: ' + $_upload.progress);
}).success(function(data, status, headers, config) {
// file is uploaded successfully
// console.log("success")
// console.log(data);
$_upload.showProg = false;
}).error(function(data, status, headers, config) {
console.log("error");
});
}
};
var UploadService = $scope.onFileSelect($files,$upload);
return UploadService;
}]);
based off this:
https://github.com/danialfarid/angular-file-upload

First and foremost, a service cannot take dependency on scope, so you cannot inject $scope (can inject $rootScope). You cannot copy and paste code from your controller implementation and paste into service.
The factory service needs to create service object and then attach functions and return at last
app.factory('UploadService',['$upload', function($upload){
var service = {};
service.upload = $upload.upload({
...
});
return service;
}]);

You can't inject $scope into a factory / service. You can use $rootScope, but you should probably be returning a promise from your factory.
Here is another similar question. Angularjs factory: errors on passing $scope,$route,$http?
app.factory('UploadService',['$upload', '$q', function($upload, $q){
var deferred = $q.defer();
return{
upload: function(uploadConfig){
$upload.upload(uploadConfig)
.success(function(data){
deferred.resolve(data);
}).error(function(error){
deferred.reject(error);
});
return deferred.promise;
}
}
}]);

Related

AngularJS Service Singleton?

I'm fairly new to angularJS but I've read that services should be singleton. However, it wont' work.
Here is my service:
.factory('TrainingPlan', function($http, SERVER){
var o = {
exercises: [],
planID : 0
};
o.init = function(){
if(o.exercises.length == 0)
return o.getAllExercises();
};
o.getAllExercises = function(){
$http({
method: 'GET',
url: SERVER.url + 'listener.php?request=getAllExercises&planID=' + o.planID
}).then(function(data){
o.exercises = angular.copy(o.exercises.concat(data.data));
console.log("Exercises in Trainingplan Services");
console.log(o.exercises);
return o.exercises;
})
;
};
o.getExercise = function(exerciseID){
for(var i = 0; i < o.exercises.length; i++){
if(o.exercises[i].exerciseID == exerciseID)
{
return o.exercises[i];
}
}
};
return o;
})
And I have two Controllers:
.controller('TrainingDetailCtrl', function($scope, $stateParams, TrainingPlan, $timeout) {
TrainingPlan.init();
$timeout(function(){
$scope.exercises = TrainingPlan.exercises;
$scope.numberOfUnfishedExercises = $scope.exercises.length;
button.innerHTML = "asdf";
}, 250);
})
(I haven't copied the whole controller, but it works so far...)
.controller('TrainingHistoryEditCtrl', function($scope, $stateParams, TrainingPlan, $timeout) {
var exerciseID = $stateParams.exerciseID;
$scope.currentExercise = TrainingPlan.getExercise(exerciseID);
console.log($scope.currentExercise);
})
So actually I go from TrainingDetailCtrl where I have all the exercises of 'TrainingPlan'. However, when I change the sites, TrainingPlan has no exercises anymore when I wont to use them in TrainingHistoryEditCtrl.
That is because your $http issues an async call. Even if you call init, actually when the code runs to the line $timeout(function(){.., the result may not arrive yet.
Please check this demo: JSFiddle. Wait for 10 seconds then the value is not empty.
Solution: return a promise from the factory. Inside the controller use then to pass in callback function.

Set Angularjs Service data to Controller Variable

I am trying to set the controllers scope variable to the data, however no luck. The console.log in the controller shows undefined. Appreciate the help!
My angular service has the following code --
service('VyrtEventService', ['$http', function($http) {
var events = [];
this.getArtistEvents = function(artistId) {
var url = '/api/users/' + artistId + '/';
var promise = $http.get(url).success(function(data, status, headers, config) {
events = data.artist.events;
console.log(events);
return events;
}).catch(function(error) {
status = 'Unable to load artist data: ' + error.message;
console.log(status);
});
return promise;
};
}]);
And I am referencing it in the controller as follows --
VyrtEventService.getArtistEvents($scope.artistId).then(function(data){
$scope.events = data.data.artist.events;
});
console.log($scope.events);
You should just set $scope.events = data in your controller cause your promise already returns data.artist.events when it resolves
To pass scope to service from anywhere in controller. Make sure you inject service .
controllersModule.controller('MyCtrl', function($scope, $filter, $http, $compile, ngTableParams, **FactoryYouwant**)
{
**FactoryYouwant**.getdata($scope.**scopeYoutwantTopass**).then (function(responseData){
var ResponseFromServer =responseData.data;
}
in service
controllersModule.factory('**FactoryYouwant**, function($http) {
var responseData = null;
return {
getdata : function(**data**){ (you dont have to use $)
responseData = $http.post or whatever actually gets you data;
return responseData;
}
};
});
I hope this helps you to call get data from service anywhere in controller.

Angularjs Service Injection Issue

I'm trying to add a service to my Angular project for the first time and running into issues injecting it within my controller.
I am getting an error of --
TypeError: Cannot read property 'get' of undefined
I'm looking to properly inject the service into the controller and ways I can improve the code for best practices/efficiency.
Thanks for the help!
I have a folder /event in my angular project with the following files --
app.js
controllers.js
directives.js
services.js
app.js file has --
'use strict';
angular.module('vyrt.event', [
'vyrt.event.controllers',
'vyrt.event.services',
'vyrt.event.directives'
]);
services.js file has --
'use strict';
angular.module('vyrt.event.services', []).
service('VyrtEventService', ['$http', function($http) {
var artistId = 0,
artist = '',
events = [],
active_event_idx = 0;
this.get = function(artistId) {
var url = '/api/users/' + artistId + '/';
$http.get(url).success(function(data, status, headers, config) {
artist = data.artist.user;
events = data.artist.events;
active_event_id = data.artist.events[0].id;
});
return artist, events, active_event_id;
}
}]);
finally, the controller has --
'use strict';
angular.module('vyrt.event.controllers', []).
controller('VyrtEventCtrl', ['$scope', function($scope, VyrtEventService) {
console.log(VyrtEventService.get($scope.artistId));
$scope.activeCampaign = function(idx) {
if (idx == VyrtEventService.active_event_idx) return true;
return false;
};
}]);
The problem is that you've forgotten to put 'VyrtEventService' in your dependency list when you define you controller:
.controller('VyrtEventCtrl', ['$scope', /* you need this ==>*/ 'VyrtEventService', function($scope, VyrtEventService) {
console.log('VyrtEventService', VyrtEventService);
$scope.activeCampaign = function(idx) {
if (idx == VyrtEventService.active_event_idx) return true;
return false;
};
}]);
Update
Your get() function has a couple of issues. First, you need to return the $http.get() call itself and then you can call then() in your controller and set the results to a property on your $scope there. Second, you can't return multiple values like that. You would have to return an array of values or an object with your desired values assigned to it.
service
this.get = function(artistId) {
var url = '/api/users/' + artistId + '/';
return $http
.get(url)
.catch(function(error){
// handle errors here
console.log('Error fething artist data: ', error);
});
}
controller
VyrtEventService
.get(artistId)
.then(function(data){
$scope.artist = data.artist.user;
$scope.events = data.artist.events;
$scope.active_event_id = data.artist.events[0].id;
});
$scope.activeCampaign = function(idx) {
return (idx == $scope.active_event_idx);
};

undefined function in timeout angularjs

I have the following controller :
app.controller('ListeSASController', function($scope, $rootScope, $routeParams, $location, userService, RefreshSASServices, $timeout){
this.IsUserLogged = function()
{
return userService.user().isLogged;
};
var promise = $timeout(RefreshSASServices.RafraichirSAS(), 100);
this.getSAS = function(){
return RefreshSASServices.getSAS();
};
$scope.$on('$locationChangeStart', function(){
RefreshSASServices.ArreterLesRafraichissements();
});
});
with the following service :
app.service('RefreshSASServices', function($http, userService, serverConfigService, $q, $timeout, $translate, constantsServices) {
var listeSAS = [];
var $this = this;
var promiseRefreshSAS;
// Getters
this.getSAS = function()
{
return listeSAS;
};
//Setters
this.clearDatas = function()
{
listeSAS = [];
};
// Communication with the server
$this.getServerUri = function()
{
return serverConfigService.getServerUri()+"majsvc/";
};
// Fonctions de rafraichissement
$this.ArreterLesRafraichissements = function()
{
if(promiseRefreshSAS !== undefined)
$timeout.cancel(promiseRefreshSAS);
};
$this.GetSASFromServer = function()
{
var promises;
if(userService.user().isLogged)
{
var uri = $this.getServerUri() + "getAllSAS/"+userService.user().UserObject._id;
promises = $http.get(uri)
.success(function(data, status, headers, config) {
// this callback will be called asynchronously
// when the response is available
return data;
}).
error(function(data, status, headers, config) {
// called asynchronously if an error occurs
// or server returns response with an error status.
return "";
});
}else{
promises = $q.when(!userService.user().isLogged)
}
return promises;
};
$this.RafraichirSAS = function () {
// functions that call
$this.GetSASFromServer()
.then(function(promise){
if(promise !== undefined && promise.data !== undefined)
{
listeSAS = promise.data;
//alert('refreshing the SAS list:' + JSON.stringify(listeSAS));
}else listeSAS = [];
promiseRefreshSAS = $timeout($this.RafraichirSAS, 3000);
})
.catch(function(error)
{
console.error("Error :", error);
promiseRefreshSAS = $timeout($this.RafraichirSAS, 7000);
});
};
});
When I load my page using routes :
.when('/listeSAS', {
templateUrl : './includes/sas/liste_sas.html',
controller : 'ListeSASController',
controllerAs : 'controller'
})
everything works fine, if my data changes on the server it gets updated on the UI, My UI is also displaying what I want. Everything is OK except that when the pages loads I get the following error :
TypeError: undefined is not a function
at file:///includes/libs/angular.js:14305:28
at completeOutstandingRequest (file:///includes/libs/angular.js:4397:10)
at file:////includes/libs/angular.js:4705:7
which is the function "timeout" of angular, and the line 14305 is :
try {
deferred.resolve(fn());
} catch(e) {
deferred.reject(e);
$exceptionHandler(e);
}
finally {
delete deferreds[promise.$$timeoutId];
}
Why angular is throwing this exception ? What did I do wrong ?
To be known :
On my login page I set 2 timeouts which I don't stop because they refresh "global" variables such as the number of private messages. Despite the error both timeout are still working.
I use node webkit with my application and it crashes maybe one in three times when I open this route (after 5-10 seconds).
Thank you for your help.
Is it that you're calling RafraichirSAS(), which returns undefined instead of passing in the function?
E.g, instead of
$timeout(RefreshSASServices.RafraichirSAS(), 100);
Do
$timeout(RefreshSASServices.RafraichirSAS, 100);

model not updating in .then method of promise angularjs

I'm really struggling with this because it should be very simple. I have a route with a controller defined called login. In my template I have the following data binding {{error}} which is defined in my controller after executing a method from a custom service, and resolving the returned promise.
Controller
app.controller("login", ['$scope','XMLMC', 'ManageSettings', function ($scope,api,ManageSettings) {
$scope.error = 'test';
$scope.login = function() {
var params = {
selfServiceInstance: "selfservice",
customerId: $scope.username,
password: $scope.password
};
var authenticated = api.request("session","selfServiceLogon",params).then(function(response) {
ManageSettings.set("session",response, $scope);
if(response.status === "ok") {
window.location.href = 'portal';
} else {
$scope.error = response["ERROR"];
console.log($scope.error);
}
});
};
}]);
The console shows Customer not registered. Showing that $scope.error has been updated appropriately, but the view never gets updated. My service is below, and please note that I am doing nothing "outside" of angular and so I should not have to $apply() anything manually.
app.factory("XMLMC", ['$http', '$q', function ($http, $q) {
function XMLMC($http, $q) {
$http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8';
var that= this;
this.prepareForPost = function(pkg) {
return JSON.stringify(pkg);
};
this.request = function(service, request, params, host, newsession) {
var def = $q.defer();
var P = def.promise;
if(request === "analystLogon") {
newsession = true;
}
var call = {
service: service,
method: request,
params: params
};
if(host) {
call.host = host;
} else {
call.host = "localhost";
}
if(newsession) {
call.newsession = "true";
}
var pkg = {
contents: this.prepareForPost(call)
};
$http.post('php/XMLMC/api.php', jQuery.param(pkg)).success(function (response,status) {
that.consume(response, def);
}).error(function (response,status) {
def.reject(response,status);
});
return P;
};
this.consume = function(response, defer) {
console.log(response);
var resp = response[0],
digested = {},
i;
digested.status = resp["attrs"]["STATUS"];
var params = resp["children"][0]["children"];
for(i=0; i < params.length; i++) {
var key = params[i]["name"];
var val = params[i]["tagData"];
digested[key] = val;
}
defer.resolve(digested);
//return digested;
};
}
return new XMLMC($http, $q);
}]);
I've created a plunk here with the code exactly as it is on my test server. The routes and etc aren't working for obvious reasons, but you can at least see the code and how it works together
http://plnkr.co/edit/AodFJfCijsp2VWxWpbR8?p=preview
And here is a further simplified plunk where everything has one scope and one controller and no routes. For some reason, this works in the plunk but the $http method fails in my server
http://plnkr.co/edit/nU4drGtpwQwFoBYBfuw8?p=preview
EDIT
Even this fails to update
var authenticated = api.request("session","selfServiceLogon",params).then(function(response) {
ManageSettings.set("session",response, $scope);
$scope.error = "foo!";
if(response.status === "ok") {
window.location.href = 'portal';
}
});
It appears that $scope.$apply is indeed needed. See AngularJS - why is $apply required to properly resolve a $q promise?
To quote #pkozlowski.opensource:
In AngularJS the results of promise resolution are propagated asynchronously, inside a $digest cycle. So, callbacks registered with then() will only be called upon entering a $digest cycle.

Categories