in html, I write follow:
<div ng-controller="cxController">
<my-dir test-data="testdata"></my-dir>
</div>
in the cxController, I write follow:
$scope.testdata={
spanInfo:{},
buttonInfo:{}
};
$scope.click1=function(){};
$scope.click2=function(){};
$scope.click3=function(){};
in directive, there are some spans and buttons. and the button number is not set, I need to use ng-repeat to write it. But the button has click function: click1,click2,click3 and so on. How can I call the function click1,click2... in the directive?
To tell the directive there are some functions in buttonInfo like this?
$scope.testdata={
spanInfo:{},
buttonInfo:{
{click:$scope.click1}
{click:$scope.click2}
}
};
This is a way , that I am used to call a controller function from a directive.
Can you make use of this?
your directive
(function() {
'use strict';
angular
.module('app')
.directive('myDir', myDir);
myDir.$inject = [];
function myDir() {
return {
restrict: 'AE',
scope: {
onClick : '&' ,
},
template: '<div>'+
'<button ng-click="onClick()"></button'+
'</div>',
link: function(scope, element, attrs) {
}
}
}
})();
controller
(function() {
'use strict';
angular
.module('app')
.controller('myController', myController);
myController.$inject = [];
function myController() {
var vm = this;
vm.callControllerFn = function(){
alert("called")
}
}
})();
View
<my-dir on-click="vmA.callControllerFn();"></my-dir>
Related
Been trying to figure this out for too long now. Maybe someone can shed some light:
Am experimenting with custom directives and as an exercise I'm trying to create a method within the custom directive's controller that can be called from a simple button within the view. But the method isn't being called, even though I can see the method (using console) as a property within isolated scope object. Any ideas please?
HTML:
<my-dir>
<p>My dir content</p>
<p><button ng-click="hideMe()">Hide element with isolated scope</button></p>
</my-dir>
JS:
var app = angular.module('myApp', []);
app.directive('myDir', function() {
return {
restrict: 'EA',
scope: {},
controller: ['$scope', function ($scope) {
$scope.hideMe = function(){
console.log('hideMe called');
};
}]
};
})
You have to declare your template inside the directive using template: property or inside an external .html file using templateUrl:"path/to/template.html"
Example using template :
var app = angular.module('myApp', []);
app.directive('myDir', function() {
return {
restrict: 'EA',
scope: {},
template : '<p>My dir content</p><p><button ng-click="hideMe()">Hide me</button></p>',
controller: ['$scope', function ($scope) {
$scope.hideMe = function(){
console.log('hideMe called');
};
}]
};
})
Example using templateUrl :
var app = angular.module('myApp', []);
app.directive('myDir', function() {
return {
restrict: 'EA',
scope: {},
templateUrl : 'my-dir.tpls.html',
controller: ['$scope', function ($scope) {
$scope.hideMe = function(){
console.log('hideMe called');
};
}]
};
})
Template : my-dir.tpls.html
<p>My dir content</p>
<p><button ng-click="hideMe()">Hide me</button></p>
HTML:
<my-dir></my-dir>
You can try this,
Directive:
app.directive('myDir', function() {
return {
restrict: 'EA',
scope: {},
link: function($scope, element, attrs) {
$scope.hideMe = function() {
alert('hideMe called');
}
}
}
});
HTML:
<div ng-controller="MyCtrl">
<my-dir>
<p>My dir content</p>
<p>
<button ng-click="hideMe()">Hide element with isolated scope</button>
</p>
</my-dir>
</div>
DEMO
I am new to AngularJS. Can anyone tell me with example that how to call a custom directive in a scope function of another controller.
For example I have a controller with a function as follows:
angularApp.controller('sample_Ctrl', function ($scope, $http, $timeout, $rootScope, $location) {
$scope.showReport = function(id) {
};
});
I created a customDirective as follows:
var showModalDirective = function ($timeout) {
return {
restrict: 'E',
templateUrl: '/Partials/template1.html',
};
};
angularApp.directive('showModal', showModalDirective);
So how to call this directive in the showReport function, and how can I pass id to template URL?
You can't call directive in controller. It should be a service.
Or you can use directive in view:
Directive:
var showModalDirective = function ($timeout) {
return {
restrict: 'E',
scope: {
modalId: '='
},
templateUrl: '/Partials/template1.html',
};
};
angularApp.directive('showModal', showModalDirective);
Controller:
angularApp.controller('sample_Ctrl', function ($scope, $http, $timeout, $rootScope, $location) {
$scope.showModal = false;
$scope.showReport = function(id) {
$scope.showModal = true;
$scope.modalId = id;
};
});
View:
<div ng-if="showModal">
<show-modal modal-id="modalId"></show-modal>
</div>
showModal directive is call when showModal variable is true.
To use your directive first u need to create HTML element with same name as your directive then provide data for that directive from your controller. Suppose there is a div in your html page.
<div show-modal> </div>
Then on this page your template1.html will call internally through directive and suppose there is some html element in template1.html like
code in your controller -
angularApp.controller('sample_Ctrl',function() {
$scope.firstName= "My First Name"
})
TL;DR I solved my problem. Here is plunker with 3 different solutions:
http://plnkr.co/edit/E0ErKs?p=preview
I don`t like slider1 because it stores value in $scope ( {{sliderValue}} ) and according to recommendation from Angular Style Guide we should avoid that.
I don`t like slider2 because it assumes that controler have alias vm in a view (so we create some kind of coupling between view and directive).
Solution 3 looks OK for me. Am I missing something?
How would you write differently this directive to be in complience with Angular philosophy?
INITIAL QUESTION:
I am learning angular and not everything is clear to me yet.
I found this question:
How to use jQuery in AngularJS
So I created working example:
Directive:
(function() {
'use strict';
angular.module('demoApp').directive('slider', function () {
return {
restrict: 'A',
controller: function ($scope, $element, $attrs) {
$scope.onSlide = function (e, ui) {
$scope.sliderValue = ui.value;
$scope.$digest();
};
},
link: function (scope, el, attrs) {
var options = {
value: scope.sliderValue,
slide: scope.onSlide
};
// set up slider on load
angular.element(document).ready(function () {
scope.$slider = $(el).slider(options);
});
}
}
});
})();
Controller:
(function() {
'use strict';
angular.module('demoApp').controller('DemoAppTestCtrl', DemoAppTestCtrl);
DemoAppTestCtrl.$inject = [ '$scope' ];
function DemoAppTestCtrl($scope) {
$scope.sliderValue = 10;
}
})();
And Html page:
<div ng-controller="DemoAppTestCtrl as vm">
Value: {{sliderValue}}
<div slider></div>
</div>
Everything works fine. Angular put slider in place of <div slider> and I can move it and I see changing values in {{sliderValue}}.
Then I found this Angular Style Guide
https://github.com/johnpapa/angular-styleguide
In chapter about controllers they recommend to use controllerAs with vm syntax (because $scope is bad or something).
Ex:
function CustomerController() {
var vm = this;
vm.name = {};
vm.sendMessage = function() { };
}
So I changed my controller to this:
(function() {
'use strict';
angular.module('demoApp').controller('DemoAppTestCtrl', DemoAppTestCtrl);
DemoAppTestCtrl.$inject = [ ];
function DemoAppTestCtrl($scope) {
var vm = this;
vm.sliderValue = 10;
}
})();
And Html page to:
<div ng-controller="DemoAppTestCtrl as vm">
Value: {{vm.sliderValue}}
<div slider></div>
</div>
But i don`t know how to fix my directive.
I want the same functionality, when i move the slider i want to set vm.sliderValue inside controler instead $scope.sliderValue inside scope.
EDIT1:
I was able to make it work by adding $scope.vm inside controller and link functions (because my controller sits in scope as vm). But I am not sure if this is right way to do it, because now my directive assume that there is controller in scope under $scope.vm alias.
Is this bad design or normal way of doing things in Angular ?
(function () {
'use strict';
angular
.module('demoApp')
.directive('slider', slider);
slider.$inject = [ ];
function slider() {
return {
restrict: 'A',
controller: function ($scope, $element, $attrs) {
$scope.vm.onSlide = function (e, ui) {
$scope.vm.sliderValue = ui.value;
$scope.$digest();
};
},
link: function (scope, el, attrs) {
var options = {
value: scope.vm.sliderValue,
slide: scope.vm.onSlide
};
// set up slider on load
angular.element(document).ready(function () {
scope.$slider = $(el).slider(options);
});
}
}
}
})();
EDIT2:
I was able to create working Plunker with 3 different versions:
http://plnkr.co/edit/E0ErKs?p=preview
Use scope: false as a option in the directive.
http://www.undefinednull.com/2014/02/11/mastering-the-scope-of-a-directive-in-angularjs/
try something like this:
angular.module('myApp', []);
angular.module('myApp').controller('DemoAppTestCtrl', DemoAppTestCtrl);
function DemoAppTestCtrl() {
var vm = this;
vm.sliderValue = 10;
}
angular.module('myApp').directive('slider', sliderDirective );
function sliderDirective() {
return {
restrict: 'A',
controller: sliderController,
controllerAs: 'sliderCtrl',
template: "<p>{{sliderCtrl.test}}</p>"
}
}
function sliderController() {
var vm = this;
vm.test = "hello";
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="DemoAppTestCtrl as vm">
Value: {{vm.sliderValue}}
<div slider></div>
</div>
</div>
I've written my own directive from which I want to call a method on the parent ng-controller. I've tried doing that by adding require:'ngController' in my directive. However the returned controller is just an empty object. I'm running 1.4.8.
<div ng-controller="myController">
<div my-directive></div>
</div>
app.directive('myDirective', function() {
return {
restrict: 'A',
scope: false,
require: '^ngController',
link: function (scope, $element, attrs, controller) {
//controller is empty object..
};
}
});
Update: My misstake was that I added a method to the controllers scope when I should add it directly to the controller instead.
app.controller('myController', function($scope) {
$scope.myMethod = function() {}; //Not callable from controller passed to directive
this.myMethod = function() {}; //IS callable from controller passed to directive
});
You can call the parent controller via scope if your directive doesn't have an isolated scope, and you don't need to require ngController.
angular.module('app', [])
.controller('controller', function($scope) {
$scope.greet = function() {
return 'hi'
};
})
.directive('testDirective', function() {
return {
restrict: 'E',
template: '<h1>{{ greet() }}</h1>'
};
});
Output:
hi
Plnkr: http://plnkr.co/edit/uGXC5i1GjphcZCPDytDG?p=preview
The function needs to be available in the directive's scope. So if your directive is in the scope of the controller it is:
scope.fn();
I'm new to angular and can't figure out how to call a directive function from the template. I have some fuctionality that will be reused throught the app and figured I would just make a directive with all the functionlity needed, that can easily be shared accross different modules. While searching for answers I came across this post: how-to-call-a-method-defined-in-an-angularjs-directive
which seems like a good solution. However, I can't seem to figure out why my directive method showPolicy() is not being called.
// controller:
(function(){
'use strict';
angular.module('releaseAppsModule')
.controller('releaseAppsController', releaseAppsController);
releaseAppsController.$inject = ['$rootScope',
'storageFactory',
'releaseAppsFactory',
'$modal',
'$translate',
'getIconFactory',
'$scope',
'$filter'];
function releaseAppsController($rootScope, storageFactory, releaseAppsFactory, $modal, $translate, getIconFactory, $scope, $filter) {
var vm = this;
vm.policyControl = {};
...
// controller template:
<tr ng-repeat="policyRelease in regionRelease.policyReleases | orderBy:vm.orderByField:vm.reverseSort" ng-if="policyRelease.status == 'NEW' || policyRelease.status == 'SCHEDULED'">
<td>
<policy control="vm.policyControl" release-item="policyRelease" class="release-apps-app-btn app-release-data"></policy>
</td>
// directive:
(function(){
'use strict';
angular.module('myApp')
.directive('policy', policy)
function policy() {
var directive = {
restrict: 'E',
link: link,
replace: true,
scope: {
releaseItem: '=',
control: '='
},
template: '<a ng-click="vm.policyControl.showPolicy({releaseItem: releaseItem});">{{ releaseItem.policy.name }}</a>'
};
return directive;
function link(scope, el, attr) {
scope.internalControl = scope.control || {};
scope.internalControl.showPolicy = function (releaseData) {
...
} // showPolicy
scope.internalControl.showPolicyModal = function(response, releaseData) {
...
} // showPolicyModal
} // link
} // policy
})();
In your template, you're trying to call vm.policyControl.showPolicy() which is undefined on your current directive scope, as Angular is attempting to find
[directiveScope].vm.policyControl.showPolicy()
You'll need to change the ng-click function to internalControl.showPolicy(), as that is referencing the actual object that the directive's scope has available.