Run document.ready with angularjs routes - angularjs

I am trying to run the function .parallax() from Materialize framework using routes in the angularjs. I already config the command document.ready for each template but this doesn't work. This works just in the first time. What is the best way to make document.ready calling functions like $('.test').test(); using routes? I will wait! Thanks!
Template HTML of my route:
<!-- JS -->
<script type="text/javascript">
$(document).ready(function(){
$('.parallax').parallax(); //Run just in the first time
};
</script>
<!-- Template -->
<div class="" ng-controller="homeCtrl">
...
</div>
Controller:
app.controller('homeCtrl', ['$scope', function($scope){
//Ready
angular.element(document).ready(function() {
$('.parallax').parallax(); // Doesn't work
});
}]);
Thanks!

Obviously the code in controller will not work as this is a single page application and by the time the controller is loaded the document is already loaded and the call back in the script tag is called. I think you can create a directive like
App.directive('testJquery', function() {
return {
restrict: 'A',
link: function(scope, element, attrs) {
$(element).parallex();
}
};
});
and the html be like, assuming your parallex class elements are present in each view of the routes
<div class="parallex" test-plugin><div>
If there is one div which is outside the ng-view and you want to call the parallex or any testFuntion on the element every time you change route then what you can do in your main controller(under which this element is there)
Change the directive to
App.directive('testJquery', function() {
return {
restrict: 'A',
scope:{
runFunctionAgain:'='
},
link: function(scope, element, attrs) {
$(element).parallex();
scope.$watch('runFunctionAgain', function(){
if(scope.runFunctionAgain){
$(element).parallex();
scope.runFunctionAgain = false;
}
})
}
};
});
And take the parameter from the controller in the directive
<div class="parallex" run-function-again="runFunctionAgain" test-plugin><div>
In the controller
scope.runFunctionAgain = true;
$scope.$on('$routeChangeStart', function (event, next, current) {
scope.runFunctionAgain = true;
});

Related

How can I replace link hrefs with ngClicks in dynamically generated HTML within AngularJS?

I'm consuming dynamically generated HTML from an API which may contain hyperlinks, and I'm wanting to replace the hrefs within them with ngClicks. The following directive appears to modify the HTML as intended when I check it in a DOM inspector, but clicking it does nothing. What am I doing wrong?
app.directive('replaceLinks', ['$compile', function ($compile) {
return {
restrict: 'A',
link: function (scope, element, attrs) {
scope.$watch(function(scope) {
return scope.$eval(attrs.replaceLinks);
}, function(value) {
element.html(value);
angular.forEach(element.contents().find("a"), function(link) {
link.removeAttribute("href");
link.removeAttribute("target");
link.setAttribute("ng-click", "alert('test')");
});
$compile(element.contents())(scope);
});
}
};
}]);
Instead of removing the href please set it to blank (this will preserve the link css), also the ng-click calling the alert can be done by calling the alert('test') inside of a scope method, why the alert didn't fire, is explained in this SO Answer, please refer the below sample code!
// <body ng-app='myApp' binds to the app being created below.
var app = angular.module('myApp', []);
app.directive('replaceLinks', ['$compile', function($compile) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
angular.forEach(element.find("a"), function(link) {
link.setAttribute("href", "");
link.removeAttribute("target");
link.setAttribute("ng-click", "scopeAlert('test')");
});
$compile(element.contents())(scope);
}
};
}]);
// Register MyController object to this app
app.controller('MyController', ['$scope', MyController]);
// We define a simple controller constructor.
function MyController($scope) {
// On controller load, assign 'World' to the "name" model
// in <input type="text" ng-model="name"></input>
$scope.name = 'World';
$scope.scopeAlert = function(name) {
window.alert(name);
}
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-controller='MyController' ng-app="myApp">
<div replace-links>
test 1
test 2
test 3
</div>
</div>

appending html from another file to div using directive

I am quite new to angularjs, I am trying to append html from another html file using my directive. I only want to do this only if I get a success callback from the server from my http request.
Currently I have my directive, I am not sure if this is the way to do it. I have also attached my directive to the div I want to append to.
host.directive('newHost', function(){
return {
restrict: 'E',
link: function(scope, element, attr){
scope.newBox = function(){
templateUrl: 'newHostTemplate.html';
};
}
}
});
I then call $scope.newBox() on my success callback which at that point I want to append to the div.
I have followed the answer below, and tried to adapt it to my scenario, however I am getting the error $scope.newBox is not a function, here is my current implementation.
host.directive('newHost', function(){
return {
restrict: 'E',
template: '<div ng-include="getTemplateUrl()"></div>',
link: function(scope, element, attr){
scope.newBox = function(){
console.log('newBox');
scope.getTemplateUrl = function(){
return 'newHostTemplate.html'
};
};
}
}
});
//controller, this does all the routing on client side
host.controller('hostsController', function($scope, $http, $window, $rootScope){
$rootScope.$on("$routeChangeError", function (event, current, previous, rejection) {
console.log("failed to change routes");
});
$scope.newHost = {};
$scope.addNewHost = function() {
$http({
method : 'POST',
url : 'http://192.168.0.99:5000/newHost',
data : JSON.stringify($scope.newHost), // pass in data as strings
})
.success(function(data) {
console.log(data);
$scope.newBox()
//on success we want to close the modal and reset the data
$scope.newHost = {}
$scope.dismiss()
});
};
});
Here are two examples:
Using ng-include and a function that points to the external file
I created a plunker showing you a working example. As soon as you click the 'process data' link, it will call NewBox() that will append the content from an external file. This link simulates your callback.
In the directive, the template is defined as template:
<div ng-include="getTemplateUrl()"></div>
And in the link function, I setup getTemplateUrl() once newBox() is called... the getTemplateUrl() function returns the name of the external file (e.g. template.html):
link: function(scope, element, attr) {
scope.newBox = function() {
console.log('new Box');
scope.getTemplateUrl = function() {
return 'template.html';
}
}
}
The full JS file is:
angular.module('components', [])
.directive('newHost', function() {
return {
restrict: 'E',
template: '<div ng-include="getTemplateUrl()"></div>',
link: function(scope, element, attr) {
scope.newBox = function() {
console.log('new Box');
scope.getTemplateUrl = function() {
return 'template.html';
}
}
}
}
});
angular.module('HelloApp', ['components'])
.controller('MyCtrl', ['$scope', function($scope) {
$scope.name = 'This is the controller';
$scope.go = function() {
console.log('Processing...');
$scope.newBox();
}
}]);
index.html is:
<!doctype html>
<html ng-app="HelloApp" >
<head>
<meta charset="utf-8">
<title>AngularJS Plunker</title>
<link rel="stylesheet" href="style.css">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular.js"></script>
<script src="app.js"></script>
</head>
<body>
<div ng-controller="MyCtrl">
<new-host></new-host>
<br/>
<a ng-href='#here' ng-click='go()'>process data</a>
</div>
</body>
</html>
And template.html is a simple example:
<div>
This is some content from template.html
</div>
If you look in plunker, once you press 'process data', the template.html content is then added using the newBox() function. Now, you would replace that link with your callback.
Using ng-show and a boolean to hide/show the content
One way which is going in a slightly different direction than you is to use ng-show and hide the template until newBox() is called.
I created a JSFiddle that shows an example of how to do this.
The new-host tag is hidden at the start using ng-show:
<div ng-controller="MyCtrl">
<new-host ng-show='displayNewHost'></new-host>
<br/>
<a ng-href='#here' ng-click='go()' >process data</a>
</div>
The link process data is to simulate your success callback, so when you click on it, it will call $scope.newBox()
Here is the main JS file:
angular.module('components',[])
.directive('newHost', function() {
return {
restrict: 'E',
link: function(scope, element, attr) {
scope.newBox = function() {
console.log('new Box');
scope.displayNewHost = true;
};
}
}
})
angular.module('HelloApp', ['components'])
function MyCtrl($scope) {
$scope.displayNewHost = false;
$scope.name = 'This is the controller';
$scope.go = function() {
console.log('Processing...');
$scope.newBox();
}
}
angular.module('myApp', ['components'])
As you see, in the controller we set displayNewHost to false hiding the directive. Once one clicks on the process data link, the newBox function sets displayNewHost to true and then the content appears.
In your example, you would replace the 'template' by 'templateUrl' pointing to your file.
That is another solution.
Editing my answer to answer the follow-up question / newBox is not a function error
Just reading your code (without checking using plunker so I may be wrong), I am guessing that the problem is that once you are in the success function $scope points to another scope. Try to change your code to this... please note that I put $scope in a variable 'vm' and then use that in both the core function and the success callback.
host.controller('hostsController', function($scope, $http, $window, $rootScope){
$rootScope.$on("$routeChangeError", function (event, current, previous, rejection) {
console.log("failed to change routes");
});
var vm = $scope;
vm.newHost = {};
vm.addNewHost = function() {
$http({
method : 'POST',
url : 'http://192.168.0.99:5000/newHost',
data : JSON.stringify(vm.newHost), // pass in data as strings
})
.success(function(data) {
console.log(data);
vm.newBox()
//on success we want to close the modal and reset the data
vm.newHost = {}
vm.dismiss()
});
};
});'

element.on('click') on a directive within ng-if doesn't work

I use a directive on links to provide a modal login, if the user isn't logged in. And it works fine for all usecases until now. In a new case the directive is part of a ng-if section.
On the snippet the first link works fine, the second doesn't work. The element.on('click', function(evt) {…}) will never called. And the permissions are not checked and no modal login will prompt to the user.
Ok, if I use ng-show instead of ng-if, both links works. Because ng-show doesn't remove the element from the DOM and it doesn't create a child scope like ng-if. But in my usecase I must use ng-if. What can I do? How can I provide a click event, which works within a ng-if and other ng-x directives too?
var app = angular.module('myapp', []);
app.controller('MyCtrl', function($timeout) {
// something stupid here
var vm = this;
vm.bar = false;
$timeout(function() {
vm.bar = true;
});
});
/**
* I need an isolate scope, because some user state checks
* will take place in the directive. And there are different
* login forms based on type and other attributes.
*/
app.directive('modalLogin', function() {
return {
restrict: 'A',
scope: {
type: '#mlType'
},
compile: function(element, attrs) {
if (element[0].nodeName !== ('A')) {
// use directive only at links
return function() {};
}
return function(scope) {
function checkPermissions() {
// do the magic here
alert('foo');
}
element.on('click', function(evt) {
evt.preventDefault();
checkPermissions();
})
}
}
}
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<section ng-app="myapp" ng-controller="MyCtrl as FOO">
<div>
<!-- it works -->
Klick me, I'm working well
</div>
<!-- it doesn't work -->
<div ng-if="FOO.bar">
Klick me, I'm nested within a ng-if
</div>
</section>
Use link instead of compile.
link: function(scope, element) {
function checkPermissions() {
alert('foo');
}
element.on('click', function(evt) {
evt.preventDefault();
checkPermissions();
});
}

Angular how to change controller scope from onclick directive

Here is my directive
.directive('closeMapMessage', function($log) {
'use strict';
return function(scope, element) {
var clickingCallback = function() {
angular.element('.map').fadeOut("slow");
};
element.bind('click', clickingCallback);
};
})
How can I change a scope variable in the controller ?
<div class="msg-mobile" ng-show="showInstructionModal">
<div class="close-map-msg ok-got-it-footer" close-map-message>Ok, got it. </div>
</div>
I basically want to set my showInstructionModalfalse when my close directive is called.
From the current snippet of code, it's hard to tell why you're not using a modal solution tailored for Angular, i.e. AngularUI's modal.
However, in your current code, you're attaching a click event to the element outside of Angular's awareness. That's why clicking on the element will not have effect until the next $digest cycle has run. Also, in Agular you normally don't use directives the way you're trying to do. I would suggest updating the directive to also provide the HTML and then use the ng-clickattribute to attach the event handler via Angular.
Update your directive's code to:
.directive('closeMapMessage', function($log) {
'use strict';
return {
restrict: "AE",
link: function(scope, element) {
scope.closeModal = function() {
angular.element('.map').fadeOut("slow");
scope.showInstructionModal = false; // probably need to put this in a $timeout for example to show the fading of the element
};
},
template: '<div class="close-map-msg ok-got-it-footer" ng-click="closeModal()">Ok, got it.</div>'
};
})
And then update your HTML accordingly:
<div class="msg-mobile" ng-show="showInstructionModal">
<close-map-message></close-map-message>
</div>
You should run digest cycle manually after click event occurrence to update all scope bindings
.directive('closeMapMessage', function($log) {
'use strict';
return function(scope, element) {
var clickingCallback = function() {
angular.element('.map').fadeOut("slow");
scope.$apply();
};
element.bind('click', clickingCallback);
};
})

How to call a method defined in an AngularJS directive?

I have a directive, here is the code :
.directive('map', function() {
return {
restrict: 'E',
replace: true,
template: '<div></div>',
link: function($scope, element, attrs) {
var center = new google.maps.LatLng(50.1, 14.4);
$scope.map_options = {
zoom: 14,
center: center,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
// create map
var map = new google.maps.Map(document.getElementById(attrs.id), $scope.map_options);
var dirService= new google.maps.DirectionsService();
var dirRenderer= new google.maps.DirectionsRenderer()
var showDirections = function(dirResult, dirStatus) {
if (dirStatus != google.maps.DirectionsStatus.OK) {
alert('Directions failed: ' + dirStatus);
return;
}
// Show directions
dirRenderer.setMap(map);
//$scope.dirRenderer.setPanel(Demo.dirContainer);
dirRenderer.setDirections(dirResult);
};
// Watch
var updateMap = function(){
dirService.route($scope.dirRequest, showDirections);
};
$scope.$watch('dirRequest.origin', updateMap);
google.maps.event.addListener(map, 'zoom_changed', function() {
$scope.map_options.zoom = map.getZoom();
});
dirService.route($scope.dirRequest, showDirections);
}
}
})
I would like to call updateMap() on a user action. The action button is not on the directive.
What is the best way to call updateMap() from a controller?
If you want to use isolated scopes you can pass a control object using bi-directional binding = of a variable from the controller scope. You can also control also several instances of the same directive on a page with the same control object.
angular.module('directiveControlDemo', [])
.controller('MainCtrl', function($scope) {
$scope.focusinControl = {};
})
.directive('focusin', function factory() {
return {
restrict: 'E',
replace: true,
template: '<div>A:{{internalControl}}</div>',
scope: {
control: '='
},
link: function(scope, element, attrs) {
scope.internalControl = scope.control || {};
scope.internalControl.takenTablets = 0;
scope.internalControl.takeTablet = function() {
scope.internalControl.takenTablets += 1;
}
}
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="directiveControlDemo">
<div ng-controller="MainCtrl">
<button ng-click="focusinControl.takeTablet()">Call directive function</button>
<p>
<b>In controller scope:</b>
{{focusinControl}}
</p>
<p>
<b>In directive scope:</b>
<focusin control="focusinControl"></focusin>
</p>
<p>
<b>Without control object:</b>
<focusin></focusin>
</p>
</div>
</div>
Assuming that the action button uses the same controller $scope as the directive, just define function updateMap on $scope inside the link function. Your controller can then call that function when the action button is clicked.
<div ng-controller="MyCtrl">
<map></map>
<button ng-click="updateMap()">call updateMap()</button>
</div>
app.directive('map', function() {
return {
restrict: 'E',
replace: true,
template: '<div></div>',
link: function($scope, element, attrs) {
$scope.updateMap = function() {
alert('inside updateMap()');
}
}
}
});
fiddle
As per #FlorianF's comment, if the directive uses an isolated scope, things are more complicated. Here's one way to make it work: add a set-fn attribute to the map directive which will register the directive function with the controller:
<map set-fn="setDirectiveFn(theDirFn)"></map>
<button ng-click="directiveFn()">call directive function</button>
scope: { setFn: '&' },
link: function(scope, element, attrs) {
scope.updateMap = function() {
alert('inside updateMap()');
}
scope.setFn({theDirFn: scope.updateMap});
}
function MyCtrl($scope) {
$scope.setDirectiveFn = function(directiveFn) {
$scope.directiveFn = directiveFn;
};
}
fiddle
Although it might be tempting to expose an object on the isolated scope of a directive to facilitate communicating with it, doing can lead to confusing "spaghetti" code, especially if you need to chain this communication through a couple levels (controller, to directive, to nested directive, etc.)
We originally went down this path but after some more research found that it made more sense and resulted in both more maintainable and readable code to expose events and properties that a directive will use for communication via a service then using $watch on that service's properties in the directive or any other controls that would need to react to those changes for communication.
This abstraction works very nicely with AngularJS's dependency injection framework as you can inject the service into any items that need to react to those events. If you look at the Angular.js file, you'll see that the directives in there also use services and $watch in this manner, they don't expose events over the isolated scope.
Lastly, in the case that you need to communicate between directives that are dependent on one another, I would recommend sharing a controller between those directives as the means of communication.
AngularJS's Wiki for Best Practices also mentions this:
Only use .$broadcast(), .$emit() and .$on() for atomic events
Events that are relevant globally across the entire app (such as a user authenticating or the app closing). If you want events specific to modules, services or widgets you should consider Services, Directive Controllers, or 3rd Party Libs
$scope.$watch() should replace the need for events
Injecting services and calling methods directly is also useful for direct communication
Directives are able to directly communicate with each other through directive-controllers
Building on Oliver's answer - you might not always need to access a directive's inner methods, and in those cases you probably don't want to have to create a blank object and add a control attr to the directive just to prevent it from throwing an error (cannot set property 'takeTablet' of undefined).
You also might want to use the method in other places within the directive.
I would add a check to make sure scope.control exists, and set methods to it in a similar fashion to the revealing module pattern
app.directive('focusin', function factory() {
return {
restrict: 'E',
replace: true,
template: '<div>A:{{control}}</div>',
scope: {
control: '='
},
link : function (scope, element, attrs) {
var takenTablets = 0;
var takeTablet = function() {
takenTablets += 1;
}
if (scope.control) {
scope.control = {
takeTablet: takeTablet
};
}
}
};
});
To be honest, I was not really convinced with any of the answers in this thread. So, here's are my solutions:
Directive Handler(Manager) Approach
This method is agnostic to whether the directive's $scope is a shared one or isolated one
A factory to register the directive instances
angular.module('myModule').factory('MyDirectiveHandler', function() {
var instance_map = {};
var service = {
registerDirective: registerDirective,
getDirective: getDirective,
deregisterDirective: deregisterDirective
};
return service;
function registerDirective(name, ctrl) {
instance_map[name] = ctrl;
}
function getDirective(name) {
return instance_map[name];
}
function deregisterDirective(name) {
instance_map[name] = null;
}
});
The directive code, I usually put all the logic that doesn't deal with DOM inside directive controller. And registering the controller instance inside our handler
angular.module('myModule').directive('myDirective', function(MyDirectiveHandler) {
var directive = {
link: link,
controller: controller
};
return directive;
function link() {
//link fn code
}
function controller($scope, $attrs) {
var name = $attrs.name;
this.updateMap = function() {
//some code
};
MyDirectiveHandler.registerDirective(name, this);
$scope.$on('destroy', function() {
MyDirectiveHandler.deregisterDirective(name);
});
}
})
template code
<div my-directive name="foo"></div>
Access the controller instance using the factory & run the publicly exposed methods
angular.module('myModule').controller('MyController', function(MyDirectiveHandler, $scope) {
$scope.someFn = function() {
MyDirectiveHandler.get('foo').updateMap();
};
});
Angular's approach
Taking a leaf out of angular's book on how they deal with
<form name="my_form"></form>
using $parse and registering controller on $parent scope. This technique doesn't work on isolated $scope directives.
angular.module('myModule').directive('myDirective', function($parse) {
var directive = {
link: link,
controller: controller,
scope: true
};
return directive;
function link() {
//link fn code
}
function controller($scope, $attrs) {
$parse($attrs.name).assign($scope.$parent, this);
this.updateMap = function() {
//some code
};
}
})
Access it inside controller using $scope.foo
angular.module('myModule').controller('MyController', function($scope) {
$scope.someFn = function() {
$scope.foo.updateMap();
};
});
A bit late, but this is a solution with the isolated scope and "events" to call a function in the directive. This solution is inspired by this SO post by satchmorun and adds a module and an API.
//Create module
var MapModule = angular.module('MapModule', []);
//Load dependency dynamically
angular.module('app').requires.push('MapModule');
Create an API to communicate with the directive. The addUpdateEvent adds an event to the event array and updateMap calls every event function.
MapModule.factory('MapApi', function () {
return {
events: [],
addUpdateEvent: function (func) {
this.events.push(func);
},
updateMap: function () {
this.events.forEach(function (func) {
func.call();
});
}
}
});
(Maybe you have to add functionality to remove event.)
In the directive set a reference to the MapAPI and add $scope.updateMap as an event when MapApi.updateMap is called.
app.directive('map', function () {
return {
restrict: 'E',
scope: {},
templateUrl: '....',
controller: function ($scope, $http, $attrs, MapApi) {
$scope.api = MapApi;
$scope.updateMap = function () {
//Update the map
};
//Add event
$scope.api.addUpdateEvent($scope.updateMap);
}
}
});
In the "main" controller add a reference to the MapApi and just call MapApi.updateMap() to update the map.
app.controller('mainController', function ($scope, MapApi) {
$scope.updateMapButtonClick = function() {
MapApi.updateMap();
};
}
You can specify a DOM attribute that can be used to allow the directive to define a function on the parent scope. The parent scope can then call this method like any other. Here's a plunker. And below is the relevant code.
clearfn is an attribute on the directive element into which the parent scope can pass a scope property which the directive can then set to a function that accomplish's the desired behavior.
<!DOCTYPE html>
<html ng-app="myapp">
<head>
<script data-require="angular.js#*" data-semver="1.3.0-beta.5" src="https://code.angularjs.org/1.3.0-beta.5/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<style>
my-box{
display:block;
border:solid 1px #aaa;
min-width:50px;
min-height:50px;
padding:.5em;
margin:1em;
outline:0px;
box-shadow:inset 0px 0px .4em #aaa;
}
</style>
</head>
<body ng-controller="mycontroller">
<h1>Call method on directive</h1>
<button ng-click="clear()">Clear</button>
<my-box clearfn="clear" contentEditable=true></my-box>
<script>
var app = angular.module('myapp', []);
app.controller('mycontroller', function($scope){
});
app.directive('myBox', function(){
return {
restrict: 'E',
scope: {
clearFn: '=clearfn'
},
template: '',
link: function(scope, element, attrs){
element.html('Hello World!');
scope.clearFn = function(){
element.html('');
};
}
}
});
</script>
</body>
</html>
Just use scope.$parent to associate function called to directive function
angular.module('myApp', [])
.controller('MyCtrl',['$scope',function($scope) {
}])
.directive('mydirective',function(){
function link(scope, el, attr){
//use scope.$parent to associate the function called to directive function
scope.$parent.myfunction = function directivefunction(parameter){
//do something
}
}
return {
link: link,
restrict: 'E'
};
});
in HTML
<div ng-controller="MyCtrl">
<mydirective></mydirective>
<button ng-click="myfunction(parameter)">call()</button>
</div>
You can tell the method name to directive to define which you want to call from controller but without isolate scope,
angular.module("app", [])
.directive("palyer", [
function() {
return {
restrict: "A",
template:'<div class="player"><span ng-bind="text"></span></div>',
link: function($scope, element, attr) {
if (attr.toPlay) {
$scope[attr.toPlay] = function(name) {
$scope.text = name + " playing...";
}
}
}
};
}
])
.controller("playerController", ["$scope",
function($scope) {
$scope.clickPlay = function() {
$scope.play('AR Song');
};
}
]);
.player{
border:1px solid;
padding: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<div ng-controller="playerController">
<p>Click play button to play
<p>
<p palyer="" to-play="play"></p>
<button ng-click="clickPlay()">Play</button>
</div>
</div>
TESTED
Hope this helps someone.
My simple approach (Think tags as your original code)
<html>
<div ng-click="myfuncion">
<my-dir callfunction="myfunction">
</html>
<directive "my-dir">
callfunction:"=callfunction"
link : function(scope,element,attr) {
scope.callfunction = function() {
/// your code
}
}
</directive>
Maybe this is not the best choice, but you can do angular.element("#element").isolateScope() or $("#element").isolateScope() to access the scope and/or the controller of your directive.
How to get a directive's controller in a page controller:
write a custom directive to get the reference to the directive controller from the DOM element:
angular.module('myApp')
.directive('controller', controller);
controller.$inject = ['$parse'];
function controller($parse) {
var directive = {
restrict: 'A',
link: linkFunction
};
return directive;
function linkFunction(scope, el, attrs) {
var directiveName = attrs.$normalize(el.prop("tagName").toLowerCase());
var directiveController = el.controller(directiveName);
var model = $parse(attrs.controller);
model.assign(scope, directiveController);
}
}
use it in the page controller's html:
<my-directive controller="vm.myDirectiveController"></my-directive>
Use the directive controller in the page controller:
vm.myDirectiveController.callSomeMethod();
Note: the given solution works only for element directives' controllers (tag name is used to get the name of the wanted directive).
Below solution will be useful when, you are having controllers (both parent and directive (isolated)) in 'controller As' format
someone might find this useful,
directive :
var directive = {
link: link,
restrict: 'E',
replace: true,
scope: {
clearFilters: '='
},
templateUrl: "/temp.html",
bindToController: true,
controller: ProjectCustomAttributesController,
controllerAs: 'vmd'
};
return directive;
function link(scope, element, attrs) {
scope.vmd.clearFilters = scope.vmd.SetFitlersToDefaultValue;
}
}
directive Controller :
function DirectiveController($location, dbConnection, uiUtility) {
vmd.SetFitlersToDefaultValue = SetFitlersToDefaultValue;
function SetFitlersToDefaultValue() {
//your logic
}
}
html code :
<Test-directive clear-filters="vm.ClearFilters"></Test-directive>
<a class="pull-right" style="cursor: pointer" ng-click="vm.ClearFilters()"><u>Clear</u></a>
//this button is from parent controller which will call directive controller function

Resources