Calling a method within a controller that's within a custom directive - angularjs

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

Related

How to handle ng-click inside directive Angular JS?

I have the following directive:
.directive("feedList", function() {
return {
restrict: 'E',
scope: {
feeds: '=feedData'
},
templateUrl: 'jstemplates/feed-list.html',
link: function(scope) {
angular.forEach(scope.feeds, function(value, key) {
if(value.who.fullname == " "){
scope.feeds[key].fullname = "email";
}
console.log(value.who.fullname);
});
}
}
})
Inside my template there is an event: ng-click="do()". How to handle this event in directive ot in parent controller?
As it's your isolated scope directive, so pass the callback function and then call that function directly from template or from controller or link function.
Working fiddle
var app = angular.module('myApp', []);
app.controller('AppCtrl', function($scope){
$scope.testFunction = function(){
alert("Called from isolated scope directive");
};
});
app.directive("isolatedScopeDirective", function(){
return{
scope:{
go:"&"
},
template : `<button ng-click='go()'>Test Button</button>`
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-controller="AppCtrl">
<isolated-scope-directive go="testFunction()"></isolated-scope-directive>
</div>

Calling controller function from directive using bindToController

I wrote a plunker to see how to use bindToDirective to isolate scopes and using directive controller to call main controller function, but, I am doing something wrong. Could you suggest?
This is the plunker: http://plnkr.co/edit/UJLjTmIiHydHr8qRzAsX?p=preview
Code sample:
.controller('Ctrl', function() {
var self = this;
self.func = function() {
console.log('In the controller function');
};
})
.directive('myDirective', [ function() {
var self = {};
self.link = function (scope, elem, attrs, ctrl) {
elem.bind('click', function () {
ctrl.ctrlFunc();
});
elem.addClass('fa fa-file-excel-o fa-lg');
};
return {
restrict: 'E',
scope: {},
controller: function () {
},
controllerAs: 'DirCtrl',
bindToController: {
ctrlFunc: '&'
},
link: self.link
};
}])
html sample to associate main controller function to directive:
<div ng-controller="Ctrl">
<my-directive ctrlfunc="Ctrl.func()"></my-directive>
</div>
You have a number of issues:
You need a hyphen in your directive argument name and you should be passing the function reference, not calling the function directly (with params):
<my-directive ctrl-func="ctrl.func"></my-directive>
Second, you are using alias syntax in your controller (var self = this;), but not in your template. You need to update it to the following:
<div ng-controller="Ctrl as ctrl">
<my-directive ctrl-func="ctrl.func"></my-directive>
</div>
Finally, pass down the function reference with two-way binding instead of with & since that passes down values for implicit evaluation.
bindToController: {
ctrlFunc: '='
},
See working plunkr
I'm not sure you need bindToController...
This version calls your Ctrl's function: http://plnkr.co/edit/Rxu5ZmmUAU8p63hR2Qge?p=preview
JS
angular.module('plunker', [])
.controller('Ctrl', function($scope) {
$scope.func = function() {
console.log('In the controller function');
};
}) angular.module('plunker', [])
.controller('Ctrl', function($scope) {
$scope.func = function() {
console.log('In the controller function');
};
})
.directive('myDirective', [ function() {
return {
template: '<pre>[clickme]</pre>',
replace: true,
restrict: 'E',
scope: {
target: '&'
},
link: function (scope, elem, attrs) {
elem.bind('click', function () {
var fn = scope.target && scope.target(scope);
fn && fn();
});
elem.addClass('fa fa-file-excel-o fa-lg');
}
};
}])
HTML
<div ng-controller="Ctrl">
<my-directive target="func"></my-directive>
</div>

angularJS how to $eval the function with parameter

I am trying to implement the directive, in the directive, I want to $eval the values which contains the function name and parameter value:
Html page:
<select mydirective="action('pValue')">
AngularJS directive code:
app.directive('mydirective', function ($timeout) {
return {
restrict: 'A',
link: function ($scope, element, attr) {
$timeout(function () {
$scope.$eval(attr.mydirective);
});
}
}
What I am expected is it will invoke the action function define in scope and pass the pValue as function parameter. How can I make it work please?
What you want happen automatically, the function will invoke with the value, this is the purpose of eval:
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
$scope.action = function(val) {
alert(val);
}
});
app.directive('mydirective', function($timeout) {
return {
restrict: 'A',
link: function($scope, element, attr) {
$timeout(function() {
$scope.$eval(attr.mydirective);
});
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.21/angular.min.js"></script>
<div ng-app="plunker" ng-controller="MainCtrl">
<select mydirective="action('pValue')"></select>
</div>
For those whom looking for a way to pass $event info to custom directive method see example below:
TEMPLATE:
<div on-touch-end="onTouchEnd( 'some data' )">
TOUCH ME!
</div>
CONTROLLER:
$scope.onTouchEnd = function( data ) {
console.log("onTouchEnd event with data", data, event );
};
DIRECTIVE:
.directive('onTouchEnd', function() {
return {
restrict : 'A',
link : function( $scope, $element, $attr ) {
$element.on('touchend', function( event ) {
$scope.$apply(function() {
$scope.$eval( $attr.onTouchEnd );
});
});
}
}
})

angularjs bind data and display from hardcode and or service

Hello i have my directive:
myApp.directive('hoverDirective',function($document){
return function(scope, element, attr){
scope:{value:'foo'};
element('mouseover',function(event){
console.log(event);
});
}
});
And I have it working:
<div hover-directive>
{{value}}
</div>
But now I want to hardcode data in directive, and get it by factory.
I read about scope:{value:'foo'}. But i have error while i was putting it inside of return function.
Can anyone help ?
UPDATE: I try putting code inside of return function no results.
Please see here : http://jsfiddle.net/qeCDL/
HTML:
<div ng-app="app">
<div ng-controller="firstCtrl">
<div hover-directive></div>
</div>
</div>
JS:
var app = angular.module('app', []);
app.directive('hoverDirective', function () {
return {
scope: {},
restrict: 'AE',
controller: function () {
},
template: '<h3>{{value}}</h3>',
link: function (scope, element, attrs) {
scope.value = "hove me";
element.on('mouseover', function (event) {
console.log(scope.value);
});
}
};
});
app.controller('firstCtrl', function ($scope) {
});

AngularJS - set a model defined in a directives template

I have a directive defined like so:
angular.module('directives.myInput', [])
.directive('myInput', function($parse, $http, $sce){
return {
restrict: 'E',
template: '<input type="text" ng-model="searchStr" />',
controller: function($scope){
$scope.keyPressed = function(event){
$scope.showDropdown = true;
.
.
.
}
}
};
});
And then I have a button in html and directive above declared like so:
<div ng-controller="IndexCtrl">
<button ng-click="startNewLog()">Start</button>
<div ng-controller="ItemNewCtrl">
<myInput />
</div>
</div>
I want to change/initialize ng-model="searchStr" model on a button ng-click. How can I do that?
Thanks guys,
Jani
If I understand you right, first of all you need call child controller with $broadcast. Since we don't use isolate scope, we just call directive method from child controller:
[Short answer]
No isolate scope example
Demo 1 Fiddle
For isolate scope, I would map value to directive that listens on value change automatically:
Isolate scope example
Demo 2 Fiddle
[Full answer]
No isolate scope example
HTML
<div ng-controller = "IndexCtrl">
<button ng-click="startNewLog()">Start</button>
<div ng-controller="ItemNewCtrl">
<my-input></my-input>
</div>
</div>
JS
var app = angular.module('myModule', []);
app.controller('IndexCtrl', function ($scope) {
$scope.startNewLog = function(){
$scope.$broadcast('someEvent');
};
});
app.controller('ItemNewCtrl', function ($scope) {
$scope.$on('someEvent', function() {
$scope.callDirective();
});
});
app.$inject = ['$scope'];
app.directive('myInput', function(){
return {
restrict: 'E',
template: '<input type="text" ng-model="searchStr" />',
controller: function($scope){
$scope.searchStr;
$scope.keyPressed = function(event){
$scope.showDropdown = true;
}
},
link: function(scope, elm, attrs) {
scope.callDirective = function() {
scope.searchStr = 'callDirective';
};
}
};
});
Isolate scope example
HTML
<div ng-controller = "IndexCtrl">
<button ng-click="startNewLog()">Start</button>
<div ng-controller="ItemNewCtrl">
<my-input my-model='contInput'></my-input>
</div>
</div>
JS
var app = angular.module('myModule', []);
app.controller('IndexCtrl', function ($scope) {
$scope.startNewLog = function(){
$scope.$broadcast('someEvent');
};
});
app.controller('ItemNewCtrl', function ($scope) {
$scope.contInput = '';
$scope.count = 0;
$scope.$on('someEvent', function() {
$scope.contInput = 'hey mate';
});
});
app.$inject = ['$scope'];
app.directive('myInput', function(){
return {
restrict: 'E',
scope:{searchStr: '=myModel'},
template: '<input type="text" ng-model="searchStr" />',
controller: function($scope){
$scope.searchStr;
$scope.keyPressed = function(event){
$scope.showDropdown = true;
}
}
};
});

Resources