Service method called in directive's controller runs but logs undefined - angularjs

I've got a directive which is used in some of my templates and handles to upload a file, where I need to inject the relative service which handles the server requests.
Here it is
angular.module("app")
.directive('addFile', ['projectService', addFile]);
function addFile(projectService) {
return {
restrict: 'E',
require: '^ngModel',
scope: {
ngModel: '#'
},
templateUrl: 'templates/add_file_form.html',
controller: ['$scope', '$state', '$stateParams', addFileCtrl]
}
function addFileCtrl($scope, $state, $stateParams) {
$scope.upload = {
//Some other properties
post: function () {
if ($scope.upload.selectedOption.type == 0) {
projectService.uploadFile($scope.upload.file, $stateParams.projectId).then(success, fail);
function success(res) {
console.log("Uploaded file with success");
$state.reload();
};
function fail(res) {
console.log("Failed to upload file");
console.log(res);
};
} else {
projectService.uploadLink($scope.upload.link, $stateParams.projectId).then(success, fail);
function success(res) {
console.log("Uploaded file with success");
$state.reload();
};
function fail(res) {
console.log("Failed to upload file");
console.log(res);
};
}
}
}
}
}
The problem is that even though the request from projectService is done successfully my log says and eventually the success function isn't called:
Error: projectService.uploadLink(...) is undefined

The dependency injected inside directive function would only be available inside directive link(preLink & postLink) function only.
If you want projectService in directive's controller then you have to inject in controller DI array & its respective controller factory function.
controller: ['$scope', '$state', '$stateParams', 'projectService', addFileCtrl]
and
function addFileCtrl($scope, $state, $stateParams, projectService) {

The problem actually was that I didn't return the promise on my service...
#Pankaj actually helped me to exclude that the problem wasn't on the directive itself.

Related

scope access when promise resolved in Angular UI-Router

I have a small question regarding scopes and promises.
I declared wiz_ids outside a promise call and I would like to access it again when the promise is resolved.
I tried to use bind() but without luck.
This is my state:
state: 'wizard',
config: {
url: '/wizard',
templateUrl: 'app/partners/wizard/wizard.html',
controller: 'WizardController',
controllerAs: 'vm',
redirectTo: 'wizard.step1',
resolve: {
/* #ngInject */
promiseData: ['$window', '$location', 'WizardDataService', function ($window, $location, WizardDataService) {
var wiz_ids = {
'wiz_install_id': $location.search().install_id,
'wiz_instance_id': $location.search().instance_id
};
return WizardDataService.getWizardData(wiz_ids)
.then(function (response) {
// How do I access wiz_ids from here? //
return response.data;
});
}]
},
}
You could return a more complex object inside then().
Something like:
return WizardDataService.getWizardData(wiz_ids)
.then(function(response) {
var data = {
wiz_ids: wiz_ids,
wiz_data: response.data
}
return data;
});
Then in controller access the individual properties accordingly

Angular - Can I use $mdDialog in Http Interceptor Service?

I'm using http interceptor to handle errors. Is it possible to use md-dialog to pop up a window showing error messages once some certain errors are captured. A circular dependency error occurs when injecting $mdDialog into the service. Where should I bind errorMsg if $mdDialog can be used in this service?
interceptor:
.factory('httpInterceptor', ['$q', '$mdDialog', function($q, $mdDialog){
return {
'response': function(res) {
var status = res.data.status;
var errorMsg = res.data.payload.message;
if(status === 'fail') {
$mdDialog.show({
// controller: ???,
// scope: ???,
templateUrl: 'error.html',
})
return $q.reject(res);
}
return res;
}
}
}])
Yes you can display the $scope variable using a controller and resolve,
$mdDialog.show({
controller: function($scope, $mdDialog){
// do something with dialog scope
},
template: '<md-dialog aria-label="My Dialog">'+
'<md-dialog-content class="sticky-container">{{test}}' +
'</md-dialog-content>' +
'<md-button ng-click=close()>Close</md-button>' +
'</md-dialog>',
controller: 'modalCtrl',
resolve: {
test: function () {
return 'test variable';
}
}
});
Controller:
app.controller('modalCtrl', function($scope, $mdDialog, test) {
$scope.test = test;
});
DEMO

Resolving resource using ui-router

I face such problem: I have abstract state:
$stateProvider.state('bookings.clients', {
url:"/clients",
abstract:true,
views:{
"#":{
templateUrl:"/Static/CrmPages/CrmMainPage.html",
controller:"CrmMainPageController",
}
},
resolve: {
clientsData:function(clientsDataService) {
return clientsDataService.loadData('ihor.korotenko#n-cube.co.uk');
},
clientsGroupsData: function (userGroupsService) {
//return "some";
return userGroupsService.api.query(function (data) {
userGroupsService.data = data;
}).$promise;
}
}
});
As you can see there are two resolve objects.
Than, I inject this objects to controller in child state:
angular.module("crmModule")
.controller("mainPageController", ['clientsGroupsData', 'clientsData', "$scope", "$rootScope", "$translate", 'clients', 'cultureProvider', '$state', function (clientsGroupsData, clientsData, $scope, $rootScope, $translate, clients, cultureProvider, $state)
My resource provider:
angular.module("crmModule")
.service("userGroupsService", ['$resource', function ($resource) {
var self = this;
self.data = [];
return {
api: $resource("/api/groupsapi/getallgroups"),
data: self.data
}
}])
Child state:
$stateProvider.state('bookings.clients.overview', {
url:"/overview",
views:{
"crm.main":{
templateUrl: "/Static/CrmPages/main-page.html",
controller:"mainPageController"
}
},
});
The problem is following: when controller instantiates I see that injected object is not empty and resolved(It`s ok), but after that I get an exception
Error: [$injector:unpr] Unknown provider: clientsGroupsDataProvider <- clientsGroupsData <- mainPageController
How can I fix this?
So I found the reason of this error, it occurs because I attach controller in html via ng-controller directive, and of course, ui-router can`t inject dependency because it doesnt intantiate controller.

Inject dependency to controller called by directive

I would like to know if it is possible (if it is, so how? :)), to inject a dependency to a controller called by a directive.
I have a controller controller called MyCtrl. Here is his signature:
app.controller('MyCtrl', function ($scope, dataService, aDependency){...}
This Controller is usually defined in my route:
.segment('myPage', {
templateUrl: templatesUrl + 'mypage.html',
resolve: {
aDependency: ['$q', 'dataService', '$location', function ($q, dataService, $location) {
var defer = $q.defer();
dataService.retrieveCCData(defer, $location);
return defer.promise;
}],
},
controller: 'MyCtrl'
})
But now, I would also like to call this controller from a directive.
Problem is that I don't know How to inject the aDependency.
It said that the provider is unknown.
Here's my directive:
app.directive('gettingStarted1', ['dataService', function (dataService) {
return {
restrict: 'E',
templateUrl: templatesUrl + 'mypage.html',
controller: 'MyCtrl',
//resolve: {
//datasources: ['dataService', function (dataService) {
//return null;
//}]
//}
};
}]);
Resolve is impossible in directive.
Some help will be appreciate
Thank you
Make aDependency a separate service.
app.provider('aDependency', function () {
this.$get = ['$q', 'dataService', '$location', function ($q, dataService, $location) {
var defer = $q.defer();
dataService.retrieveCCData(defer, $location);
return defer.promise;
}];
});
You can resolve it with
resolve: {
'aDependency': 'aDependency',
}
or
resolve: ['aDependency'];
you could use the controller Function from the directive
.directive("sampledirective", function (dependancy1, dependancy2, ....) {
return {
scope: '=',
controller: function ($rootScope, $scope) {
//DO your controller magic here where you got your scope stuff
}
}
})
One thing i learned it seems the $scope values arent immediatly updated from directive to Controller. If you use objects like
$scope.smth.smth = 'test'
It gets updated immediatly else you would need to $apply

Loading controller on demand using AngularJS and RequireJS

I'm using Angular UI-router and trying to download/load controller when the routing changes. I used resolve and category, the data.data returns the js file content as string. I'm not sure to make the controller available to angular. Please help
My module.js contains below routing code
state("privacy", {
url: "/privacy",
controllerProvider: function ($stateParams) {
return "PrivacyController";
},
resolve: {
category: ['$http', '$stateParams', function ($http, $stateParams) {
return $http.get("js/privacy.js").then(function (data) {
return data.data;
});
} ]
},
templateUrl: localPath + "templates/privacy.html"
})
The below controller exist in "js/privacy.js"
socialinviter.controller("PrivacyController", function ($scope) {
$scope.me = "Hellow world";
});
I also tried with require js but I'm getting error "http://errors.angularjs.org/1.2.16/ng/areq?p0=PrivacyController&p1=not%20aNaNunction%2C%20got%20undefined"
resolve: {
deps: function ($q, $rootScope) {
var deferred = $q.defer(),
dependencies = ["js/privacy"];
require(dependencies, function () {
$rootScope.$apply(function () {
deferred.resolve();
});
deferred.resolve()
})
return deferred.promise;
}
}
I have resolved the issue and I thought the solution would be helpful for others
Step 1: On your config, include the parameter $controllerProvider
mytestapp.config(function ($stateProvider, $controllerProvider)
Step 2: telling angular to register the downloaded controller as controller, add the below inside the config
mytestapp.config(function ($stateProvider, $controllerProvider) {
mytestapp._controller = mytestapp.controller
mytestapp.controller = function (name, constructor){
$controllerProvider.register(name, constructor);
return (this);
}
......
Step 3: Add the resolve method as below
state("privacy", {
url: "/privacy",
controller: "PrivacyController",
resolve: {
deps : function ($q, $rootScope) {
var deferred = $q.defer();
require(["js/privacy"], function (tt) {
$rootScope.$apply(function () {
deferred.resolve();
});
deferred.resolve()
});
return deferred.promise;
}
},
templateUrl: "templates/privacy.html"
})

Resources