Access angular controller from directive - angularjs

When I have a controller inside my html
<div ng-controller="myController" id="myCtrl">...</div>
I can access it via:
angular.element(myCtrl).controller()
But how can I access the controller from a directive?
directive('myDirective', function () {
return {
...
templateUrl: '/Views/myview.html',
controller: myController
}
})

This controller should be defined the same module module where your directive is defined:
E.g
angular.module('myModule', [])
.controller('myController',['$scope', function($scope){
$scope.myData = {'someData':1337};
}])
.directive('myDirective', [function(){
return {
...
templateUrl: '/Views/myview.html',
controller: 'myController'
}
}])
Here is a plunkr, demonstrating that way:
http://plnkr.co/edit/UDCWUI5EMlfoXb9u3GYh?p=preview
And here is a plunkr, demonstrating having a directive in a module using a controller that is defined in another module:
http://plnkr.co/edit/Gg0BzKPOqO2NnTgf3Hkr?p=preview
angular.module('myApp',[
])
.controller('MyController', ['$scope', function($scope){
$scope.someValue = 'someValueFromController';
}])
angular.module('otherModule', ['myApp'])
.directive('myDirective', [function(){
return {
restrict: 'E',
templateUrl: 'someTemplate.html',
controller: 'MyController'
}
}])
Alternatively, you can use the $controller service to instantiate your controller with the appropriate stuffs and use it everywhere (from every module that imports the module where your controller is defined).

Related

AngularJS directive scope property doesn't render in directive view

I have a problem with scope property of directive that doesn't render want to render in directive view.
app.js
.config(function ($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'views/main.html',
controller: 'MainCtrl',
controllerAs: 'main'
})
main.js
angular.module('todayfmApp')
.controller('MainCtrl', ['$scope', function ($scope) {
this.formsetup = [];
this.formsetup.title = "Find Your Break";
}]);
mainController View - where Form Setup: {{main.formsetup.title}} is rendering properly
<h2>Form Setup: {{main.formsetup.title}}</h2>
<section class="home-banner">
<carousel-partial></carousel-partial>
<overlay-form formsetup="main.formsetup.title"></overlay-form>
directive
angular.
module('directives').
directive('overlayForm', function() {
return {
restrict: 'E',
scope: {
formsetup: '='
},
controller: [ '$http', '$scope',
function OverlayFormController($http, $scope) {
var self = this;
self.getResponseData = function(){
$http.get('data/form-data.json').then(function(response) {
self.formdata = response.data;
});
}
this.logResponseData = function() {
console.log(self.formdata);
}
this.getResponseData();
}
],
controllerAs: 'Ctrl',
bindToController: true,
templateUrl: 'scripts/directives/overlay-form/overlay-form.template.html',
};
});
Directive View
<div class="overlay-form">
<h3>{{formsetup.title}}</h3>
Problem is with template binding.It should be:(when you use controllerAs you need to refer view elements with the alias name)
<div class="overlay-form">
<h3>{{Ctrl.formsetup.title}}</h3>
</div>
And directive HTML code should be:
<overlay-form formsetup="main.formsetup"></overlay-form>
Please check Plunker for more understanding of how it works.

Passing params into angular directive controller

I have a controller which has some custom UI router resolve params injected:
uxgroups.controller('UXGroupStepCtrl', ['$scope', '$rootScope', '$stateParams', 'stepData', function ($scope, $rootScope, $stateParams, stepData) {
But when using this controller in my directive I am getting errors that stepData is undefined:
angular.js:14682 Error: [$injector:unpr] http://errors.angularjs.org/1.5.8/$injector/unpr?p0=stepDataProvider%20%3C-%20stepData%20%3C-%20UXGroupStepCtrl%20%3C-%20UXGroupStepCtrl
which is :
Unknown provider: stepDataProvider <- stepData <- UXGroupStepCtrl <- UXGroupStepCtrl
Here is directive definition:
app.directive('passProcess', function (stepData) {
return {
restrict: 'E',
controller: 'UXGroupStepCtrl',
scope: { p: '=' },
templateUrl: '/App/Modules/UXGroup/Views/process.html'
};
});
Is there a way to dismiss or define the extra params in my directive controller?
You can't pass data to controller from a directive like that. But the controller has the same scope as the directive. So what you can do is set a $scope variable in the directive and reference it in the controller.
app.directive('passProcess', function (stepData) {
return {
restrict: 'E',
controller: 'UXGroupStepCtrl',
scope: { p: '=' },
templateUrl: '/App/Modules/UXGroup/Views/process.html'
};
});
uxgroups.controller('UXGroupStepCtrl', ['$scope', '$rootScope', '$stateParams',
function ($scope, $rootScope, $stateParams) {
$scope.variable = $scope.p
}
Just found this other question Injecting resolves into directive controllers
which suggests it cannot be done, and best way is to make a separate controller for the directive

How to inject services into a directive?

I tried to use Angular boostrap-ui in a directive but it didn't work, so I decided to use a service which will use the Angular bootstarp-ui , and to inject it into directive.
I'm keep getting this error :
Unknown provider: ui.bootstrapProvider <- ui.bootstrap <- modal <- monitorCardDirective
The Angular app :
'use strict';
var app = angular.module('app', [ 'ui.bootstrap' ,'restangular']);
app.controller('nav', function($scope, $uibModal, $filter, Restangular) {
$scope.search = false;
});
app.directive('monitorCard',['modal',function(modal) {
return {
link: function(scope, element, attr) {
element.bind('click',function(){
modal.open({
templateUrl: 'monitoController.html',
controller: 'monitorController'
});
});
},
scope:{
monitorCard: '='
}
};
}]);
app.factory('modal',['ui.bootstrap',function($uibModal){
var modalInstance = $uibModal.open({
templateUrl: 'monitoController.html',
controller: 'monitorController'
});
return modalInstance;
}]);
In the definition of your modal factory, replace:
app.factory('modal', ['ui.bootstrap', function($uibModal)
with
app.factory('modal', ['$uibModal', function($uibModal)
As a side note, notice this factory returns a modal instance. A modal instance object is not a modal service and doesn't have an open method, so you will get another error. Judging at the directive you are defining, it seems you just need to inject uibModal service in the directive.

Take a controller of Angular directive

Consider we have some directive with templateUrl and controller.
angular.module('someApp').directive('myDirective', [function() {
return {
templateUrl:'someTemplate.html',
controller: ['$scope', function($scope) {
this.someFunction = function() {}
}]
}
}])
If we try to get controller now
var directive = angular.element('<my-directive />');
$compile(directive)( scope );
var controller = directive.controller('myDirective');
the controller is undefined.
The answer is to set a template instead of templateUrl in the directive.
angular.module('someApp').directive('myDirective', [function() {
return {
template:'<span>Solution!</span>',
controller: ['$scope', function($scope) {
this.someFunction = function() {}
}]
}
}])
I can't find anything about it in documentation. I think it's a bug.

AngularJS - How to Use Service in Template

I can access a service such as $routeParams from the controller like so.
angular.module('myModule', []).
controller('myCtrl', ['$routeParams',
'$scope', function($routeParams,
$scope) {
console.log($routeParams['my-route-param']);
}])
But how would I do the same from a template. I tried the following code to no avail.
<h1 ng-hide="$routeParams['my-route-param']">No route param!</h1>
I know you could always save the value to $scope, but I am looking for a cleaner solution.
You can assign routeParams to a property of $scope:
controller('myCtrl', ['$routeParams',
'$scope', function($routeParams,
$scope) {
...
$scope.$routeParams = $routeParams
...
}
and then this would work:
<h1 ng-hide="$routeParams['my-route-param']">No route param!</h1>
Reason for that is every property you are accessing from template should be defined in current scope, which of course is not the case for parameter of controller constructor.
NB: in case of controller as syntax used you would do the same with controller, not scope:
controller('myCtrl', ['$routeParams',
'$scope', function($routeParams,
$scope) {
...
this.$routeParams = $routeParams
...
}
and markup:
<div ng-controller="myCtrl as ctrl">
<h1 ng-hide="ctrl.$routeParams['my-route-param']">No route param!</h1>
It's a bit late, but I had enough of copying $routeParams into my $scope only to be able to use them in my views, so I created a directive to do so.
Let's say you have this routing config:
...
angular.module( 'myApp' ).config( [ '$routeProvider', function( $routeProvider ) {
$routeProvider.when( '/view1/:param1/:param2', {
templateUrl: 'view1/view1.html',
controller: 'View1Ctrl'
});
}])
...
And in your view1.html:
<h1 isteven-rr>$routeParams says: [[param1]] [[param2]]</h1>
If you have this in your URL bar: http://localhost/#/view1/Hello/World!
Then you'll see:
$routeParams says: Hello World!
Fork & learn more: https://github.com/isteven/angular-route-rage
Hope it can help shorten development time! Cheers!

Resources