AngularJs how to call prettyprint? - angularjs

I'm trying to use prettyprint plugin for my angularjs app.
But cannot make it works. I create a simple directive and call method prettyPrint(), but the code is not formatted.
FIDDLE: http://jsfiddle.net/Tropicalista/yAv4f/2/
App.directive('test', function() {
return {
restrict: 'A',
link: function(scope, element, attrs) {
$(element).prettyPrint()
}
};
});

I modified your code and i'll update here:
http://jsfiddle.net/yAv4f/6/
html:
<div ng-app="Knob" ng-controller="myCtrl">
<pre class="prettyprint linemus"></pre>
<pre class="prettyprint linemus"><!DOCTYPE html><html lang="en"></html></pre>
</div>
javascript:
var App = angular.module('Knob', []);
App.controller('myCtrl', function($scope) {
$scope.dom = '<!DOCTYPE html><html lang="en"></html>'
})
App.directive('prettyprint', function() {
return {
restrict: 'C',
link: function postLink(scope, element, attrs) {
element.html(prettyPrintOne(scope.dom));
}
};
});
Basically, you need to use the file prettify.js to control the execution of the prettify() function, with prettyPrintOne() you can execute it in a specific html text.
And to simplify the use of the directive, like prettify stlyle, i'll suggest restric to 'C' a class and change the the directive name to 'prettyprint'

I've expanded on the previous answers and created a jsfiddle with a working directive that responds in realtime to model changes:
http://jsfiddle.net/smithkl42/cwrgLd0L/27/
HTML:
<div ng-app="prettifyTest" ng-controller="myCtrl">
<div>
<input type="text" ng-model="organization.message" />
</div>
<prettify target="organization"><pre><code class="prettyprint">console.log('{{target.message}}');
</code>
</pre>
</prettify>
</div>
JS:
var App = angular.module('prettifyTest', []);
App.controller('myCtrl', function ($scope) {
$scope.organization = {
message: 'Hello, world!'
};
});
App.directive('prettify', ['$compile', '$timeout', function ($compile, $timeout) {
return {
restrict: 'E',
scope: {
target: '='
},
link: function (scope, element, attrs) {
var template = element.html();
var templateFn = $compile(template);
var update = function(){
$timeout(function () {
var compiled = templateFn(scope).html();
var prettified = prettyPrintOne(compiled);
element.html(prettified);
}, 0);
}
scope.$watch('target', function () {
update();
}, true);
update();
}
};
}]);
h/t to #DanielSchaffer (see Template always compiles with old scope value in directive).

Angular already has this filter built-in for JSON:
<pre>
{{data | json}}
</pre>
If you want to make your own directive, you can use the JSON object directly:
app.filter('prettyJSON', function () {
function syntaxHighlight(json) {
return JSON ? JSON.stringify(json, null, ' ') : 'your browser doesnt support JSON so cant pretty print';
}
return syntaxHighlight;
});
With markup
<pre>
{{data | prettyJSON}}
</pre>

I would like to make a small addition to the directive by #carlosmantilla
You can achieve the same thing without creating the scope variable. I have added this correction on github
This should work properly I assume.
http://jsfiddle.net/yAv4f/143/
var App = angular.module('Knob', []);
App.controller('myCtrl', function($scope) {
$scope.text = "function f1(){int a;}";
})
function replaceText(str)
{
var str1 = String(str);
return str1.replace(/\n/g,"<br/>");
}
app.directive('prettyprint', function() {
return {
restrict: 'C',
link: function postLink(scope, element, attrs) {
element.html(prettyPrintOne(replaceText(element.html()),'',true));
}
};
});

I struggled with this issue for quite a while and wanted to chime in here, albeit much later than everyone else (for real though, who's still using AngularJS in late 2017? This guy.) My specific use-case was where I have code (xml) being dynamically loaded on the page which needed to be pretty printed over and over again.
This directive will take in your code as an attribute, remove the prettyprinted class that's added to the element right after you run prettyPrint(). It will watch for changes on the inputted code from the parent's scope and run the code again when changes occur.
Only dependency is that you have Google's code-prettify. I had it self-hosted, hence the PR.prettyPrint() (as instructed in the docs as of sept 2017).
The directive fully encapsulates the needed Google code-prettify functionality for dynamic content.
angular.module('acrSelect.portal.directives')
.directive('prettyPrint', ['$timeout', function($timeout) {
return {
restrict: 'E',
scope: {
'code': '=',
},
template: '<pre ng-class="{prettyprint: code}">{{ code }}</pre>',
link: function (scope, element, attr) {
scope.$watch('code',function(){
$timeout(function() {
//DOM has finished rendering
PR.prettyPrint();
element.find(".prettyprint").removeClass("prettyprinted");
});
});
}
}
}
]);
The html in the parent template might look
<pretty-print code="selectedCode" ng-show="codeIsSelected"></pretty-print>
Hope this helps another poor soul!

Related

Convert string to date in AngularJS directive

I'm trying to convert a string date so that it works on a html input with the type set to 'date'.
So, I have the following angular app:
(function() {
var app = angular.module('test', []);
app.controller('MainCtrl', function($scope) {
$scope.load = function() {
$scope.message='2017-12-23T00:00:00Z';
};
});
app.directive('convertDate', function() {
return {
restrict: 'A',
scope: {
ngModel: '='
},
link: function (scope) {
console.log(scope);
console.log(scope.ngModel);
if (scope.ngModel) scope.ngModel = new Date(scope.ngModel);
}
};
});
})();
Then my html is as follows:
<div ng-controller='MainCtrl'>
<input type="date" convert-date ng-model="message">
<button ng-click="load()">load</button>
</div>
When I click on the load button I get the following error:
Error: [ngModel:datefmt] http://errors.angularjs.org/1.6.4/ngModel/datefmt?p0=2017-12-23T00%3A00%3A00Z
I understand the error is because it's a string and I need a date, which its the reason for my directive.
But even with the directive I still get the error.
What am I missing?
Thanks
Colin
You can change your directive to following:
angular.module('app').directive('convertDate', function() {
return {
require: 'ngModel',
link: function(scope, elem, attrs, ctrl) {
if (!ctrl) return;
ctrl.$parsers.push(function(date) {
if (angular.isDate(date))
return new Date(date);
})
}
}
})
take a look at this working plunkr without error
https://plnkr.co/edit/8aSR1dlsRfDMrM7GfQQa?p=preview
It is because you are using same variable in ng-model for converting. So it encounters an error before your directive converts it.
According to me, you should convert it first and then assign to the ng-model variable in your controller.
Like this,
(function() {
var app = angular.module('test', []);
app.controller('MainCtrl', function($scope) {
$scope.load = function() {
var dateString = '2017-12-23T00:00:00Z';
$scope.message=new Date(dateString);
};
});
})();
No need to use directive

Angular.js passing parameter to directive

I'm a newbie at Angular, so don't be surprise if the answer to this question is pretty basic.
I'm trying to encapsulate a map in a directive, the map will have some custom behavior: I want it to communicate with a Service to retrieve all the points related to a merchant.
So I want to pass the merchant as a parameter to the directive:
This is the HTML:
<div ng-app="myApp">
<div ng-controller="Ctrl1">
<p>Ctrl 1: {{merchant1}}</p>
<map merchantDetails="{{merchant1}}"></map>
</div>
</div>
This is the javascript:
var myApp = angular.module('myApp', []);
myApp.controller('Ctrl1', function ($scope) {
$scope.merchant1 = "foo"
});
myApp.controller('Ctrl2', function ($scope) {
$scope.merchant2 = "bar"
})
.directive('map', function () {
return {
restrict: 'E',
link: function (scope, element, attrs, controller) {
scope.merchant2 = attrs.merchantDetails;
},
scope: {
merchantDetails: "#"
},
template: 'Ctrl2: {{merchant2}}'
}
});
The problem is that scope.merchant2 at the template never gets updated.
I would like it to have "foo", or at worst "bar", not blank.
When I debug this in Chrome, controller Ctrl2 initialization is never executed. Why? I would expect it to be done before the link phase.
How do I do to get the "foo" value passed to Ctrl2?
The jsfiddle is available here.
You actually don't need the second controller.
I update the fiddler, please check if it's what you need:
https://jsfiddle.net/e7cfcakv/7/
<div ng-app="myApp">
<div ng-controller="Ctrl1">
<p>Ctrl 1: {{merchant1}}</p>
<map merchant-details="{{merchant1}}"></map>
</div>
</div>
var myApp = angular.module('myApp', []);
myApp.controller('Ctrl1', function ($scope) {
$scope.merchant1 = "foo"
});
myApp.directive('map', function () {
return {
restrict: 'E',
link: function (scope, element, attrs, controller) {
scope.merchant2 = scope.merchantDetails;
},
scope: {
merchantDetails: "#"
},
template: 'Ctrl2: {{merchant2}}'
}
});
You were almoust there
just change de directive attribute :
<map merchant-details="{{merchant1}}"></map>
Angular expects "-" before uppercase
Follow the angular js naming convention
just change the attribute "merchantDetails" to "merchant-details"
<map merchant-details="{{merchant1}}"></map>

Does dynamically adding ng-bind directive not work?

I'm adding the attribute ng-bind='data' to an element through a directive
myApp.directive('myDiv', function() {
return {
restrict: 'E',
link: function($scope, element, attrs) {
element.html('<div ng-bind="data">me</div>');
} }; });
function MyCtrl($scope) {
$('#click').click(function() {
$scope.data = 'change';
}); }
but the ng-bind isn't working as expected.
http://jsfiddle.net/HB7LU/3427/
To answer the main question your issue here is that if you want to include bindings in your template you need to compile the element. The syntax for that is something like:
$compile(angular.element("my html"))(scope)
In your case that actually ends up looking like:
myApp.directive('myDiv', function($compile) {
return {
restrict: 'E',
link: function(scope, element, attrs) {
// here adding the ng-bind dynamically
element.html($compile(angular.element('<div ng-bind="data">me</div>'))(scope));
}
};
});
To see it working checkout the updated fiddle here: http://jsfiddle.net/CC8BK/.
One other note is you are using jQuery's "click" event to change scope values. When working with angular you need to start by trying not to use jQuery and instead using the angular directives for whatever you can. In your case ng-click is the directive you should be using. I inserted this in your html so you could see what it would look like.
Hope this puts you on the right track. Best of luck!
As #drew_w said you have to compile element using $compile if you need to apply from link,
or else you can use template in directure like
template: '<div ng-bind="data"></div>'
I mostly prefer template
Also don't use jquery function like
$('#click').click(function() {
$scope.data = 'change';
});
instead you can use
$scope.change = function()
{
$scope.data = 'change';
}
or
ng-click="data = 'change'"
as #drew_w said
Take a look the full code
Working demo
html
<div ng-controller="MyCtrl">Hello, {{name}}!
<button id='click' ng-click="change()">click to 'change'</button>
<my-div>watch, this doesn't change!!!???</my-div>
</div>
script
var myApp = angular.module('myApp', []);
myApp.directive('myDiv', function ($compile) {
return {
restrict: 'E',
template:'<div ng-bind="data"></div>'
};
});
myApp.controller('MyCtrl', function ($scope) {
$scope.data = "me";
$scope.name = 'Superhero';
$scope.change = function () {
$scope.data = 'change';
}
});
here's a variation of the above answer using the Template property and using a click function:
myApp.directive('myDiv', function() {
return {
restrict: 'E',
template:'<div ng-bind="data"></div> me'
};
});
and on the controller:
$scope.click = function() {
$scope.data = 'change';
};
and on the View
<button ng-click="click()">click to 'change'</button>
http://jsfiddle.net/HB7LU/3446/

Angularjs directive depends on outer directive

I need to develop a workflow editor in Angularjs
This requires a directive(inner) that should add a div with some data and data for this directive should come from another directive(outer)
series of divs will be added right, top or bottom based on parameters.
Since you didn't post any code or exact requirements, please take a look on this demo where it shows calling directive from other directive:
HTML
<div ng-controller="MyCtrl">
<div directive-foo></div>
JS
var app = angular.module('myApp',[]);
app.directive('directiveFoo', function() {
return {
template: '<div directive-bar="123">bar</div>',
replace: true,
controller: function() {
console.log('in foo ctrl');
this.isFooAlive = function() {
return 'Foo is alive and well';
}
}
}
});
app.directive('directiveBar', function() {
return {
controller: function() {
console.log('in bar ctrl');
},
require: 'directiveFoo',
link: function(scope, element, attrs, fooCtrl) {
console.log(fooCtrl.isFooAlive());
}
}
});
function MyCtrl($scope) {
}
FIDDLE DEMO
Hope it will help you

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