I have a controller that i want to use in my directive, how can i use controller for directive i want to access all controller functions in directive ?
directive.js
angular.module('App').directive('deleteButtons', function (prcDeleteFactory,$rootScope) {
'use strict';
return{
restrict:'E',
scope:{
id: '=ids',
name: '#'
},
templateUrl:'scripts/common/prcDeleteDirective.html',
link:function(scope){
scope.deleteButton = function(){
if(scope.name === 'process') {
prcDeleteFactory.deleteObj(scope.name,scope.id);
$rootScope.$broadcast('event');
} else if(scope.name === 'risk') {
prcDeleteFactory.deleteObj(scope.name,scope.id);
} else if(scope.name === 'control'){
prcDeleteFactory.deleteObj(scope.name,scope.id);
}
}
}
}
});
Ctrl.js
angular.module('App').controller('ProcessCtrl', function($scope) {
'use strict';
$scope.confirmationWin = function(){
console.log('Print value');
};
});
You can define a controller using an anonymous function or by passing the string of an existing controller function registered on the same module like below.
return {
restrict:'E',
controller : 'ProcessCtrl'
};
As you're using an isolated scope for your directive, to access controller properties and methods, you had to define the controller explicitly.
In case you don't want to use an isolated scope, you can remove the scope property from your Directive Definition Object that you're returning., The default value is false which means your directive will share the same scope as the enclosing container's controller. You can set scope : true which means your directive will get a new scope which prototypically inherits all methods and properties from the enclosing controller.
For more details on directive scopes, you can refer to this link.
in your directive you can use
controller : 'ProcessCtrl',
controllerAs: 'vm',
bindToController: true
and then access controller properties in your directive template with vm.confirmationWin for example
Related
Here the Sample Link
I tried to Implement Modal window. I find some sample from online and I Implemented.
Here I Added the Sample file for modal window. which is working fine.
what I exactly need is while open the model window I will call this function.
$scope.callType = {};
$scope.dataFormDialog = function (id) {
$scope.callType.id = id;
exDialog.openPrime({
scope: $scope,
template: '_Product.html',
controller: 'productController',
width: '450px',
//animation: false,
//grayBackground: false
});
};
Here I Am calling _Product.html and productController from sampleController.
Modal window Invoking from sampleController that time.
How to pass the $scope value of sampleController to productController?
Can any one help me on this?...
try this
$scope.dataFormDialog = function (id) {
$scope.callType.id = id;
exDialog.openPrime({
template: '_Product.html',
controller: 'productController',
width: '450px',
resolve: {
Scopevariable: function () {
return $scope;
}
//animation: false,
//grayBackground: false
});
};
app.controller('productController', ["Scopevariable",
function (Scopevariable)
{
// use Scopevariable
}]);
To pass a scope to controller of ng-dialog there is property scope you can assign it with any object and that object and its properties you can use in dialog's controller.
Example -
$scope.value = true;
ngDialog.open({
template: 'externalTemplate.html',
className: 'ngdialog-theme-plain',
scope: $scope
});
<script type="text/ng-template" id="externalTemplate.html">
<p>External scope: <code>{{value}}</code></p>
</script>
In above example you have a value object in $scope. In dialog passing the whole $scope so can access all properties of $scope in externalTemplate.html.
For details check these ng-dialog scope
I have two directives: directiveA and directiveB, hanging from the same module in my AngularJS application.
They are called at the same level in the same HTML template, so we could say they are brothers.
<directive-a>
<directive-b>
Both of them have an own method hanging from its scope, like this:
$scope.clickOkey = function () {
... whatever
};
They both have a 'clickOkey' method, but their behaviours are different.
My problem comes out when I try to call the 'clickOkey' of directiveA from directiveA's template. It executes the 'clickOkey' from directiveB.
Inside directiveA's own template:
<label ng-click="clickOkey()">Okey</label>
They are placed at same level so there it shouldn't be way for them to share their $scope or misunderstanding methods.
Also, is important to say that if I change the method's name to 'clickOkeyA', for example, it takes the right method, so the template can access to its scope without problems.
What am I missing?
Thanks for your help!
Edit:
Both directives are isolated and have a controller, and inside each one of them is defined a 'clickOkey' method. There are two methods with the same name.
Both directives are like this:
angular.module('myModule').directive('directiveA', function () {
return {
restrict: 'AE',
templateUrl: '/whatever.html',
controller: function ($scope, $http, $rootScope) {
$scope.clickOkey = function () {
... whatever
};
}
}
});
You should add an isolated scope to your directives :
https://docs.angularjs.org/guide/directive
For your directive it would be :
angular.module('myModule').directive('directiveA', function () {
return {
restrict: 'AE',
templateUrl: '/whatever.html',
scope : {},
controller: function ($scope, $http, $rootScope) {
$scope.clickOkey = function () {
... whatever
};
}
}
});
So I have this directive that has its own scope but I want to access to a function inside its parent controller. I can do this if the parent controller exposes the function with a $scope.getElementsList(), although I'm trying to avoid the use of $scope and I have the function exposed with self.getElementsList() and the directive cannot reach it.
Directive:
angular.module('myApp').directive('accountBalance', function() {
return {
scope: {
elementId: '=elementid'
},
transclude: true,
restrict: 'E',
templateUrl: '../views_directives/account-balance.html',
controller: function($scope) {
$scope.removeElement = function(){
//this where I want to access the parent function
console.log($scope.$parent.getElementsList());
console.log("ALSO I WANT TO ACCESS THIS DIRECTIVE elementId WITHOUT USING $scope", $scope.elementId);
}
}
};
});
ParentController:
angular.module('myApp').controller('AppDesignCtrl', function ($scope) {
var self = this;
self.elementsList = [];
self.getElementsList = function(){
return self.elementsList;
}
});
I also want to know what is the best way to access, inside the directive controller, the data passed to the directive's $scope.
scope: {
elementId: '=elementid'
},
UPDATE
<div>
<i class="fa fa-arrows element-drag"></i>
<i class="fa fa-trash-o element-remove" ng-click="removeElement()"></i>
</div>
And what about calling functions from the directive template inside the controller of the directive? Do I need to expose them with something like $scope.removeElement()? How do I use this.removeElement() and be able to access it from the template?
Sorry about the long question. I'm trying to set the best practices to my new project since I've been away from angular for a year+.
Thanks in advance
(Going from bottom to top...)
To call functions in the controller without using the scope in Angular >= 1.2, use the controllerAs syntax:
<div ng-controller="AppDesignCtrl as appDesignCtrl">
...
<i class="fa fa-trash-o element-remove" ng-click="appDesignCtrl.removeElement()"></i>
</div>
And removeElement() must be a method of the controller:
angular.module('myApp').controller('AppDesignCtrl', function ($scope) {
...
this.removeElement = function() {
...
};
});
To access the scope data from the controller in Angular >= 1.3, use the new bindToController: true configuration (this is especially useful when combined with the new controllerAs syntax):
angular.module('myApp').directive('accountBalance', function() {
return {
...
scope: {
elementId: '=elementid'
},
controller: function() {
// now elementId is a member of the controller:
console.log(this.elementId);
}
};
});
Having said these, the answer to how you can call getElementsList from the directive would be:
angular.module('myApp').directive('accountBalance', function() {
return {
...
scope: {
elementId: '=elementid',
getElementList: '&'
},
controller: function() {
...
// invoking the expression that was passed to us
var theElements = this.getElementList();
}
};
});
The correct expression should be passed as:
<div ng-controller="AppDesignCtrl as appDesignCtrl">
<account-balance element-id="xxx"
get-elements-list="appDesignCtrl.getElementsList()"></account-balance>
</div>
It is generally not recommended, because directives are meant to be self-contained. It isn't critical if you don't plan to reuse the directive. And wise usage of isolate scope can solve this.
angular.module('myApp').directive('accountBalance', function() {
return {
scope: {
outerScope: '#'
elementId: '='
},
transclude: true,
restrict: 'E',
templateUrl: '../views_directives/account-balance.html',
controller: function($scope) {
console.log("we can use anything from other controller", $scope.outerScope.elementsList)
$scope.elementId = "and share data with any other scope";
}
};
});
Controller is defined as ng-controller="AppDesignCtrl as appDesign", and directive usage is
<account-balance element-id="sharedParentScopeVar" outer-scope="appDesign">
So there won't be any problem if the directive should be moved to other controller.
I guess 'best practice' may be to set up a service that embraces the data and is used by both app controller and directive, so directive controller operates on data items and not DOM elements.
And what about calling functions from the directive template inside
the controller of the directive? Do I need to expose them with
something like $scope.removeElement()?
You surely don't. If there's a need to use functions from outside, you're doing something wrong. Send a message to respective element to run the function if it is DOM-related. Or put the function into the service if it is data-related.
I try to put in my directive a way to different template, based on a $scope value. I use directive inside ng-repeat and i send her the object of datas and a other direct input
directive :
/**
* angular-streamlist directive
*/
angular.module('ngStreamlist', []).directive('webcams', function() {
return {
restrict: 'A',
scope: {
stream_webcam: '=webcam',
stream_margin: '#margin'
},
templateUrl: function(elem, attr) {
if (scope.stream_webcam.webcam_domain) {
if (scope.stream_webcam.webcam_domain == 'youtube') {
return 'templates/youtube.html';
}
if (scope.stream_webcam.webcam_domain == 'twitcam') {
return 'templates/twitcam.html';
}
}
}
};
});
html :
<div data-ng-repeat="webcam in datas.webcams">
<div data-webcams data-webcam="webcam" data-margin="no"></div>
</div>
and data is like :
{
"id": 1,
"webcam_domain": "youtube", ... etc
}
I have this error :
ReferenceError: scope is not defined
at Object.templateUrl (streamlist.js:13)
I don't understand, scope IS defined, no ?
The problem is that scope is not a local variable available to your templateUrl function. It is a field on the same object. You should be able to access it with this.scope so long as the calling angular code doesn't set this to another object.
You need to add the scope to your templateUrl function as well like so:
templateUrl: function(scope, elem, attr)
Otherwise your function won't have access to it, hence your error message.
So I want to create a nested struture on my nested scope inside a directive like this:
angular.module('myAddress').directive('myAddress', [function () {
return {
restrict: 'AE',
controller: 'myAddressController',
templateUrl: 'my-address.html',
scope: {
address: {
'form': '=addressForm',
'model': '=addressModel'
}
}
};
}]);
But I get an exception that undefined is not a function that I don't get if I remove the address nesting.
How do I put attribute arguments inside a named key on my scope?
Also, If I define $scope.address via the controller it doesn't work as well. But what will execute first? The scope: { 'form' = 'addressForm'} part in my directive or the controller's $scope.form?
With the scope property you define which $scope variables should pass to the directive scope and the type of data-binding.
If you want to create an nested structure within the directive $scope, you could create it in the directive controller function.
For example:
angular.module('myAddress').directive('myAddress', [function () {
return {
restrict: 'AE',
controller: 'myAddressController',
templateUrl: 'my-address.html',
scope: {
addressForm: '=', // Two-way databinding
addressModel: '='
},
controller: function($scope){
$scope.address = {
form: $scope.addressForm,
model: $scope.addressModel
}
},
link: function($scope,$element,$attributes){
//Your code here
}
};
}]);
You can also, define $scope.address in the module controller scope. Then your scope property in the directive should be look like this
scope: {
address: '='
}
UPDATE:
Another question is: Does your directive need an dedicated scope? If not you could set the scope property false. Then your directive can access the $scope variables in your module controller.