Use ngModel setViewValue from controller - javascript

I bind an array of values to a number of input elements. There are directives on the input elements, that set $parsers, $formatters and $validators. The controller should not care about the pipeline from viewValue to modelValue.
The view:
<ul>
<li ng-repeat="value in main.values">
<input ng-model="value.v" twice /> {{value.v}}
</li>
</ul>
Controller / Directive:
function MainController($scope) {
this.values = [
{v: 1}, {v: 2}, {v: 3}
];
}
function twice() {
return {
require: 'ngModel',
link: function(scope, elem, attr, ngModel) {
ngModel.$formatters.push(function(x) { return 2 * x });
ngModel.$parsers.push(function(x) { return 0.5 * x });
}
}
}
I want to implement a copy & paste feature. The values in all the input elements should be overwritten from clipboard data. Therefore the controller implements a function which parses the clipboard data and sets the value for each input element. The values from clipboard are view values. Since the controller has no idea how to calculate model values from these view values, it has to use the '$parsers' pipeline from 'ngModelController'. How can I implement MainController.paste() to set the view value on each input element?
Edit
I currently solved the actual problem (see comments) with a directive on the list element. http://plnkr.co/edit/9c2q2X?p=preview
function pasteValues() {
return {
link: function(scope, elem, attr, ngModel) {
elem.on('paste', function($event) {
var data = $event.clipboardData || window.clipboardData;
var text = data.getData('Text');
var values = text.split(' ');
var inputs = elem.find('input');
if (values.length === inputs.length) {
for(var i = 0, e = values.length; i != e; ++i) {
var input = inputs[i];
var ngModel = angular.element(input).controller('ngModel');
ngModel.$setViewValue(values[i]);
input.value = values[i];
}
$event.preventDefault();
}
})
}
}
}

I found two possible solutions (while writing the question:-)). http://plnkr.co/edit/ZNfYKTvSf6coGsohRlot?p=preview
1
The first is not really the angular way, because the controller has to know about DOM structure. But it is straighforward and doesn't need additional bindings and watches. To set the view value it uses the angular.element.controller() method to retrieve the ngModelController for each input element.
function MainController($scope) {
this.paste = function() {
var value = this.pasteValue;
var inputs = angular.element(document.getElementById('values')).find('input');
angular.forEach(inputs, function(input) {
var ngModel = angular.element(input).controller('ngModel');
ngModel.$setViewValue(value);
input.value = value;
});
};
}
2
The second solution is more the angular way and uses an addtional directive that whatches on paste data.
function setView() {
return {
require: 'ngModel',
scope: {
setView : '='
},
link: function(scope, elem, attr, ngModel) {
scope.$watch('setView', function(newValue) {
if (angular.isDefined(newValue)) {
elem.val(newValue);
ngModel.$setViewValue(newValue);
}
})
}
}
}
function MainController($scope) {
this.paste = function() {
var value = this.pasteValue;
this.values.forEach(function(v) { v.i = value });
};
}
The view:
<ul>
<li ng-repeat="value in main.values">
<input ng-model="value.v" twice set-view="value.i"/> {{value.i}}({{value.v}})
</li>
</ul>

Related

how to create custom Directive in angular

i was trying a sample pagination for that i have created an directive like this(am not sure its correct)
(function() {
app.directive("myPagination", function() {
return {
restrict: 'E',
templateUrl: 'pag.html'
};
});
})();
and my pag.html is
<ul class="pagination" ng-controller="PagingController">
<li ng-repeat="x in pageing" ng-click="change(x.pageno)">{{x.pageno}}</li>
</ul>
and my PageingController is like this
app.controller('PagingController', function($scope) {
$scope.$on('pageinfo', function(event, args) {
$scope.numbtn = args.numbtn;
$scope.totaldata = args.totaldata;
$scope.selet = args.selet;
$scope.starter();
})
$scope.starter = function() {
$scope.pageing = [];
let i;
for (i = 0; i < $scope.numbtn; i++) {
$scope.pageing[i] = i;
}
console.log($scope.pageing);
}
$scope.change = function(btnclk) {
alert(btnclk);
}
});
and <my-pagination></my-pagination> this is how i tried in index page. but the problem is its not showing anything even no errors can any one correct this please
Add the PageingController controller to directive instead of the template
(function() {
app.directive("myPagination", function() {
return {
restrict: 'E',
templateUrl: 'pag.html',
controller : 'PagingController'
};
});
})()
Demo
Make sure subscriber event $on is executing. otherwise page array is empty

Using different controllers with custom directive in AngularJS?

I have created a search box which is being used on two different views, one is for searching jobs and the other is for searching companies. I have made two separate controllers for both and separate services as well.
Here is the html for the searchbox -
<span class="searchButton"><i class="fa fa-search fa-2x"></i></span>
<input ng-change="companies.search()"
ng-model="companies.searchTerm"
ng-keydown="companies.deleteTerm($event)"
type="text" id="search-box"
style="width: 0px; visibility:hidden;"/>
Here is a script i am using for styling it -
<script type="text/javascript">
var toggleVar = true;
$('.searchButton').on('click', function() {
if(toggleVar) {
$('.searchButton').animate({right: '210px'}, 400);
$('#search-box').css("visibility", "visible");
setTimeout(function() {
$('.searchButton').css("color", "#444444");
}, 200);
$('#search-box').animate({ width: 185 }, 400).focus();
toggleVar = false;
}
else {
$('#search-box').animate({ width: 0 }, 400);
$('.searchButton').animate({right: '25px'}, 400);
setTimeout(function() {
$('.searchButton').css("color", "#eeeeee");
}, 300);
toggleVar = true;
}
});
$('#search-box').focusout(function() {
if(!toggleVar) {
$('#search-box').animate({ width: 0 }, 400);
$('.searchButton').animate({right: '25px'}, 400);
setTimeout(function() {
$('.searchButton').css("color", "#eeeeee");
}, 300);
toggleVar = true;
}
});
</script>
Controller -
angular.module('jobSeekerApp')
.controller('CompaniesallCtrl', ['getAllCompanies', function (companiesService) {
var ctrl = this;
var count;
ctrl.pageNumber = 1;
ctrl.searchPageNumber = 1;
ctrl.isSearching = false;
ctrl.searchTerm = "";
// Initial page load
companiesService.getCompanies(ctrl.pageNumber)
.then(function(response) {
ctrl.companiesList = response.data.results;
count = response.data.count;
checkCount();
}, function(error) {
console.log(error);
});
// User clicks next button
ctrl.getNext = function() {
// If search is not being used
if(ctrl.searchTerm === "" && ctrl.isSearching === false) {
ctrl.pageNumber = ctrl.pageNumber + 1;
companiesService.getCompanies(ctrl.pageNumber)
.then(function(response) {
ctrl.companiesList = ctrl.companiesList.concat(response.data.results);
checkCount();
}, function(error) {
console.log(error);
});
}
// If search is being used
else {
ctrl.searchPageNumber = ctrl.searchPageNumber + 1;
companiesService.searchCompany(ctrl.searchPageNumber, ctrl.searchTerm)
.then(function(response) {
ctrl.companiesList = ctrl.companiesList.concat(response.data.results);
checkCount();
}, function(error) {
console.log(error);
});
}
};
// User backspaces to delete search term
ctrl.deleteTerm = function (event) {
if(event.keyCode === 8) {
ctrl.searchTermLen = ctrl.searchTermLen - 1;
}
// If search box is empty
ctrl.isSearching = ctrl.searchTermLen !== 0;
};
// User clicks search button
ctrl.search = function() {
ctrl.searchTermLen = ctrl.searchTerm.length;
// If search box is empty, show normal results
if(ctrl.searchTerm === "" && ctrl.isSearching === false) {
ctrl.pageNumber = 1;
companiesService.getCompanies(ctrl.pageNumber)
.then(function(response) {
ctrl.companiesList = response.data.results;
count = response.data.count;
checkCount();
}, function(error) {
console.log(error);
});
}
// If search box is not empty, search the input
else {
ctrl.isSearching = true;
ctrl.searchPageNumber = 1;
companiesService.searchCompany(ctrl.searchPageNumber, ctrl.searchTerm)
.then(function(response) {
ctrl.companiesList = response.data.results;
count = response.data.count;
checkCount();
}, function(error) {
console.log(error);
});
}
};
// Function to hide and show next button
function checkCount() {
console.log(count);
$(".nextButton").toggle(count > 10);
count = count - 10;
}
}]);
I am trying to make a directive for this, since all this code is being repeated for the both the views. But how do I make the directive interact with different controllers. And how do i make this part ng-change="companies.search()" ng-model="companies.searchTerm" ng-keydown="companies.deleteTerm($event)" not dependent on the controllers.
I am new to angular and am not sure if this is the right approach or should i let the keep the code separate? Please help.
Server-Side search logic makes it simple
If it is possible that your search logic resides on the server and searching jobs or companies could be distinguished by simply setting a query variable in the URL, then it easy. You could use 1 search directive with an attribute to say which module to search and include this in your HTTP request.
Client-Side search logic slightly more angularjs
If you need different client-side logic for each type of search, consider this approach where there is 1 common search directive, plus 1 directive for each customized search.
the common search directive controls view + common search functionality
a search-companies directive that is restrict: 'A' and require: 'search' and performs functions specific to the company search
a search-jobs directive that is also restrict: 'A' and require: 'search' and performs functions specific to the job search
The concept is that the custom search directives will provide their controller/api object to the common search directive. The common search directive handles the view-controller interaction and calls the provided API functions for customized search functionality.
In Code, this could look something like:
angular.module('SearchDemo', [])
.directive('search', function(){
return {
restrict: 'E',
templateUrl: '/templates/search.tpl.html',
controller: ['$scope', function($scope){
$scope.results = [];
this.setSearchAPI = function(searchAPI){
this.api = searchAPI;
};
$scope.doSearch = function(query){
$scope.results.length = 0;
// here we call one of the custom controller functions
if(this.api && angular.isFunction(this.api.getResults)){
var results = this.api.getResults(query);
// append the results onto $scope.results
// without creating a new array
$scope.results.push.apply($scope.results, results);
}
};
}]
};
})
.directive('searchCompanies', function(){
return {
restrict: 'A',
require: ['search', 'searchCompanies'],
link: function(scope, elem, attr, Ctrl){
// here we pass the custom search-companies controller
// to the common search controller
Ctrl[0].setSearchAPI(Ctrl[1]);
},
controller: ['$scope', function($scope){
// you need to design your common search API and
// implement the custom versions of those functions here
// example:
this.getResults = function(query){
// TODO: load the results for company search
};
}]
};
})
.directive('searchJobs', function(){
return {
restrict: 'A',
require: ['search', 'searchJobs'],
link: function(scope, elem, attr, Ctrl){
// here we pass the custom search-jobs controller
// to the common search controller
Ctrl[0].setSearchAPI(Ctrl[1]);
},
controller: ['$scope', function($scope){
// you need to design your common search API and
// implement the custom versions of those functions here
// example:
this.getResults = function(query){
// TODO: load the results for job search
};
}]
};
});
And using it in template would look like:
<search search-companies></search>
and
<search search-jobs></search>
Multiple searches on one directive
This concept could be easily expanded if you need to have one search directive that searches both companies and jobs.
The change would be to turn the search controller's this.api into an array.
angular.module('SearchDemo', [])
.directive('search', function(){
return {
restrict: 'E',
templateUrl: '/templates/search.tpl.html',
controller: ['$scope', function($scope){
$scope.results = [];
// this.api is now an array and can support
// multiple custom search controllers
this.api = [];
this.addSearchAPI = function(searchAPI){
if(this.api.indexOf(searchAPI) == -1){
this.api.push(searchAPI);
}
};
$scope.doSearch = function(query){
$scope.results.length = 0;
// here we call each of the custom controller functions
for(var i=0; i < this.api.length; i++){
var api = this.api[i];
if(angular.isFunction(api.getResults)){
var results = api.getResults(query);
$scope.results.push.apply($scope.results, results);
}
}
};
}]
};
})
.directive('searchCompanies', function(){
return {
restrict: 'A',
require: ['search', 'searchCompanies'],
link: function(scope, elem, attr, Ctrl){
// here we pass the custom search-companies controller
// to the common search controller
Ctrl[0].addSearchAPI(Ctrl[1]);
},
controller: ['$scope', function($scope){
// you need to design your common search API and
// implement the custom versions of those functions here
// example:
this.getResults = function(query){
// TODO: load the results for company search
};
}]
};
})
.directive('searchJobs', function(){
return {
restrict: 'A',
require: ['search', 'searchJobs'],
link: function(scope, elem, attr, Ctrl){
// here we pass the custom search-jobs controller
// to the common search controller
Ctrl[0].addSearchAPI(Ctrl[1]);
},
controller: ['$scope', function($scope){
// you need to design your common search API and
// implement the custom versions of those functions here
// example:
this.getResults = function(query){
// TODO: load the results for job search
};
}]
};
});
And using it in template would look like:
<search search-companies search-jobs></search>
You will have to pass your data source or service to the directive and bind the events from there.
<body ng-app="customSearchDirective">
<div ng-controller="Controller">
<input type="text" placeholder="Search a Company" data-custom-search data-source="companies" />
<input type="text" placeholder="Search for People" data-custom-search data-source="people" />
<hr>
Searching In: {{ searchSource }}
<br/>
Search Result is At: {{ results }}
</div>
</body>
In this sample I am using data-source to pass an array but you can use a service of course.
Then your directive should use the scope attribute to assign what you passed as parameter in source to the scope of the directive.
You will have the input that is using the directive in the elem parameter to bind all the parameters your desire.
(function(angular) {
'use strict';
angular.module('customSearchDirective', [])
.controller('Controller', ['$scope', function($scope) {
$scope.companies = ['Microsoft', 'ID Software', 'Tesla'];
$scope.people = ['Gill Bates', 'Cohn Jarmack', 'Melon Musk'];
$scope.results = [];
$scope.searchSource = [];
}])
.directive('customSearch', [function() {
function link(scope, element, attrs) {
element.on("change", function(e) {
var searchTerm = e.target.value;
scope.$parent.$apply(function() {
scope.$parent.searchSource = scope.source;
scope.$parent.results = scope.source.indexOf(searchTerm);
});
});
}
return {
scope: {
source: '='
},
link: link
};
}]);
})(window.angular);
Using scope.$parent feels a bit hacky I know and limits the use of this directive to be a direct child of the controller but I think it's a good way to get you started.
You can try it out: https://plnkr.co/edit/A3jzjek6hyjK4Btk34Vc?p=preview
Just a couple of notes from the example.
The change event work after you remove focus from the text box (not while you're typing
You will have to search the exact string to get a match
Hope it helps.

add two elements at the same time

I have create a nested directive (a multitabbed form directive), here is simplified:
<outer>
<inner heading="a" src="'a.html'" active="true"></inner>
<inner heading="b" src="'b.html'"></inner>
</outer>
This create ul/li tabset, when I click on tab the li will be active and div related to that tab will become visible too.
This is my directives:
(function(){
'use strict'
angular
.module("testDirective", [])
.directive("outer", outer)
.directive("inner", inner);
function outer(){
return {
templateUrl: 'outer.html',
transclude: true,
controller: function($scope){
var tabs = $scope.tabs = [];
this.addTab = function(_active, _name) {
tabs.push({
active : _active,
name : _name
});
}
$scope.toggle = function(ix){
for (var i = 0; i <= tabs.length - 1; i++) {
tabs[i].active = false;
}
tabs[ix].active = true;
}
}
}
}
function inner(){
return {
require: '^outer',
scope: {
src : '=',
active : '=',
},
templateUrl: 'inner.html',
link : function(s, e, a, ctrl) {
ctrl.addTab(a.active, a.heading);
}
}
}
})();
I successfully implement everything except one part that cause me headaches: how can I show/hide content? This is a plunkr.
Here is a solution:
Modification to index.html:
<outer>
<inner heading="a" src="'a.html'" index="0" active=true></inner>
<inner heading="b" src="'b.html'" index="1"></inner>
</outer>
InnerHTML:
<ng-include ng-class="isActive()" src="src"></ng-include>
Added the following function to outer function:
this.isActive = function (index) {
if(tabs[index] && tabs[index].active){
return "ng-show";
} else {
return "ng-hide";
}
};
Added modified inner link function like so:
link : function(s, e, a, ctrl) {
ctrl.addTab(a.active, a.heading);
s.isActive = function () {
return ctrl.isActive(a.index);
};
}
http://plnkr.co/edit/c311iIKEGRGyBPMFbzi8?p=preview

What's the best way to implement a single tri-state checkbox within angularjs?

Is there a simple way to place a single tri-state checkbox on a web-page and bind it to a boolean model so the latter can take true, false or null values?
The closest solution I found so far is http://jsfiddle.net/HB7LU/454/ but it has a flaw when setting up an initial view state (as there is no way to get a model value during first rendering). Any other suggestions deal with multiple child checkboxes and solves the problem by watching on them.
http://jsfiddle.net/xJhEG/ I made it in a commercial project. Tristates are true, false, null (not "unknown")
.directive('indeterminate', [function() {
return {
require: '?ngModel',
link: function(scope, el, attrs, ctrl) {
var truthy = true;
var falsy = false;
var nully = null;
ctrl.$formatters = [];
ctrl.$parsers = [];
ctrl.$render = function() {
var d = ctrl.$viewValue;
el.data('checked', d);
switch(d){
case truthy:
el.prop('indeterminate', false);
el.prop('checked', true);
break;
case falsy:
el.prop('indeterminate', false);
el.prop('checked', false);
break;
default:
el.prop('indeterminate', true);
}
};
el.bind('click', function() {
var d;
switch(el.data('checked')){
case falsy:
d = truthy;
break;
case truthy:
d = nully;
break;
default:
d = falsy;
}
ctrl.$setViewValue(d);
scope.$apply(ctrl.$render);
});
}
};
}])
Here my Fiddle, starting from TruongSinh and changing
http://jsfiddle.net/xJhEG/25/
without
var truthy = true;
var falsy = false;
var nully = null;
You have take advantage of the indeterminate state of <input type="checkbox">.
MDN web docs:
There exists an indeterminate state of checkboxes, one in which it is not checked or unchecked, but undetermined. This is set using the HTMLInputElement object's indeterminate property via JavaScript (it cannot be set using an HTML attribute).
PLUNKER: TRISTATE DIRECTIVE
HTML
<label>
<input type="checkbox" ng-model="state" indeterminate /> {{state}}
</label>
DIRECTIVE
app.directive('indeterminate', function() {
return {
restrict: 'A',
scope: {
model: '=ngModel'
},
link: function(scope, el, attrs, ctrl) {
var states = [true, false, undefined];
var index = states.indexOf(scope.model);
setIndeterminate();
el.bind('click', function() {
scope.model = states[++index % 3];
setIndeterminate();
});
function setIndeterminate() {
scope.$applyAsync(function() {
el[0].indeterminate = (scope.model === undefined);
});
}
}
};
});
I've created directive, which you can use.
Three-state checkbox AngularJS Directive on GitHub
There is also a post, how it was built: Creating Angular Directive "Three-state checkbox
You can try a DEMO
And the directive looks like that:
angular.module("threeStateCheckbox", [])
.directive("threeStateCheckbox", ['$compile', function($compile){
return {
restrict: "A",
transclude: true,
require: 'ngModel',
link: function(scope, element, attrs, ngModel){
var states = [true, false, null];
var classNames = ["checked", "unchecked", "clear"];
scope.click = function(){
var st;
states.map(function(val, i){
if(ngModel.$modelValue === val){
st = states[(i+1)%3];
}
});
ngModel.$setViewValue(st);
ngModel.$render();
};
scope.tscClassName = function(){
var className;
states.map(function(val, i){
if(ngModel.$modelValue=== val){
className = classNames[i];
}
});
return className;
};
element.attr("class", "tri-sta-che ");
element.attr("ng-click", "click()");
element.attr("ng-class", "tscClassName()");
element.removeAttr("three-state-checkbox");
$compile(element)(scope);
}
};
}]);
Because all previous answers don't work since AngularJS 1.7 (the checkbox model only allows boolean values now and everything else gets converted to boolean), I now found a solution that works until v1.8:
Thanks to #The.Bear for the base.
To use it, simply include <tristate label="someOptionalText" ng-model="yourVariableToBindTo" /> and the corresponding directive.
var app = angular.module('tristatedemo', []);
app.controller('MyCtrl', function() {
this.state = null; //initial state
});
app.directive('tristate', function() {
return {
restrict: 'E',
scope: {
model: '=ngModel',
label: '#'
},
template: '<input type="checkbox" /> {{label}}',
link: function(scope, el, attrs, ctrl) {
var states = [true, false, null];
var index = states.indexOf(scope.model);
setIndeterminate();
el.bind('click', function() {
scope.model = states[++index % 3];
setIndeterminate();
});
function setIndeterminate() {
scope.$applyAsync(function() {
var cb = el.find('input')[0];
cb.checked = scope.model;
cb.indeterminate = (scope.model === null);
});
}
},
};
});
<!DOCTYPE html>
<html ng-app="tristatedemo">
<head>
<script data-require="angular.js#1.8.x" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.8.2/angular.min.js" data-semver="1.8.2"></script>
</head>
<body ng-controller="MyCtrl as ctrl">
{{(ctrl.state === null) ? "null" : ctrl.state}}<br> <!-- only for demo -->
<tristate label="abc" ng-model="ctrl.state" />
</body>
</html>

Angular.js updating SVG templates in directives

A while ago I asked about "Angular.js rendering SVG templates in directives", where I was replacing the DOM nodes that angular makes when rendering templates, with SVG nodes. I got a response that answered it for me, but I realized that I lost all the databindings from angular.
See Plunkr (click update): http://plnkr.co/edit/HjOpqc?p=preview
How do I replace these DOM nodes with SVG nodes, and leave my angular bindings intact? I tried using $compile to make it work (as I've done with regular html), but its just not working.
code:
var svgNS = 'http://www.w3.org/2000/svg';
app.directive('path', ngSvg('path'));
app.directive('g', ngSvg('g'));
function ngSvg(type) {
return function($timeout, $compile) {
return {
restrict: 'E',
link: function(scope, el, attr) {
//skip nodes if they are already svg
if (el[0].namespaceURI === svgNS) {
return;
}
// I would expect the chunk of code below to work,
// but it does not with ng-repeat
// var newAttr = {};
// _.each(el[0].attributes, function(at) {
// newAttr[at.nodeName] = at.value;
// });
// var path = makeNode(type, el, newAttr);
// var parent = path.cloneNode(true);
// $compile(parent)(scope);
// var children = el.children();
// $(parent).append(children);
// $timeout(function() {
// el.replaceWith(parent);
// })
// this works for rendering, but does not update the svg elements
// when update is clicked
$timeout(function() {
var newAttr = {};
_.each(el[0].attributes, function(at) {
newAttr[at.nodeName] = at.value;
});
var path = makeNode(type, el, newAttr);
var parent = path.cloneNode(true);
var children = el.children();
$(parent).append(children);
el.replaceWith(parent);
});
}
}
}
}
/* Create a shape node with the given settings. */
function makeNode(name, element, settings) {
// var ns = 'http://www.w3.org/2000/svg';
var node = document.createElementNS(svgNS, name);
for (var attribute in settings) {
var value = settings[attribute];
if (value !== null && value !== null && !attribute.match(/\$/) &&
(typeof value !== 'string' || value !== '')) {
node.setAttribute(attribute, value);
}
}
return node;
}
This issue is solved in Angular 1.3 and here is an implementation of some custom svg directives with the behaviors you would expect from an Angular directive. There is now a special requirement is on the directive declaration as follows templateNamespace: 'svg'
Also notice I am overriding some reserved attributes, for example, x and height in regards to <rect/>. To retain more control over these you can leverage ng-attr as such '<rect ng-attr-width="{{ ngWidth }}" />
JSFiddle Link
Here is a custom <rect/> and <circle/>
app.directive('ngRect', [function () {
return {
templateNamespace: 'svg',
replace: true,
template: '<rect ng-attr-width="{{ ngWidth }}" ng-attr-height="{{ ngHeight }}" ng-attr-x="{{ ngX }}" ng-attr-y="{{ ngY }}" ng-click="ngRectClick()"/>',
scope: {
'ngHeight': '=',
'ngWidth': '='
},
link: function (scope, elem, attrs) {
scope.ngRectClick = function() {
console.log(elem);
}
}
}
}]);
app.directive('ngCircle', [function () {
return {
templateNamespace: 'svg',
replace: true,
template: '<circle ng-attr-cx="{{ ngCx }}" ng-attr-cy="{{ ngCy }}" ng-attr-r="{{ ngR }}" ng-attr-fill="{{ ngFill }}" ng-click="ngCircleClick()"/>',
scope: {
'ngCx': '=',
'ngCy': '=',
'ngR': '=',
'ngFill': '='
},
link: function (scope, elem, attrs) {
scope.ngCircleClick = function() {
console.log(elem);
}
}
}
}]);

Categories