How to attach event to dom created in link function - javascript

I know that dom created in template function can be attached to an event in controller.As:
angular.module('app', [])
.directive('appClick', function(){
return {
restrict: 'A',
scope: true,
template: '<button ng-click="click()">Click me</button> Clicked {{clicked}} times',
controller: function($scope, $element){
$scope.clicked = 0;
$scope.click = function(){
$scope.clicked++
}
}
}
});
As there is no scope in template so I have to use link function.
The same how can I achieve in link function. Like:
angular.module('app', [])
.directive('appClick', function(){
return {
restrict: 'A',
scope: true,
link:function(scope, element, attrs){
element.html('<button ng-click="click()">Click me</button> Clicked {{clicked}} times')
},
controller: function($scope, $element){
$scope.clicked = 0;
$scope.click = function(){
$scope.clicked++
}
}
}
});
How to attach event here.

In Angularjs when you want to attach some DOM to the existing DOM. You first have to compile it with the $compile service on the scope for which you want to use the template. This is because template contain Angular js template syntax. Below is the working snippets.
var myApp = angular.module('myApp', []);
myApp.controller('mainController', ['$scope', function($scope){
$scope.message = 'Welcome message';
}])
myApp.directive('myTemplate', ['$compile',function($compile) {
return {
restrict: 'A',
scope: true,
link: function(scope, element, attr) {
var el = $compile('<button ng-click="click()">Click me</button> Clicked {{clicked}} times')(scope);
element.append(el);
scope.clicked = 0;
scope.click = function(){
scope.clicked++
}
}
}
}])
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="mainController">
{{message}}
<div my-template></div>
</div>
</div>

angular.module('app', [])
.directive('appClick', function(){
return {
restrict: 'A',
scope: true,
link:function(scope, element, attrs){
element.html('<button ng-click="click()">Click me</button> Clicked {{clicked}} times')
scope.clicked = 0;
scope.click = function(){
scope.clicked++
}
}
});
Achieve this without controller.

Related

Where to define a local function in a AngularJS Directive

Where do I have to define my function button() in the directive, such that pressing the button will trigger the function?
I don't want to use the outer scope of the app, I just want to use the local scope.
var app = angular.module("myApp", []);
app.directive('aaaa', function() {
return {
restrict: 'E',
scope: {
data: '=',
//this is not working: button: function(){console.log('hello from button');}
},
link: function(scope, element) {
element.append('hello');
element.append(' <button type="button" ng-click="button()">Click Me!</button> ')
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div ng-app="myApp">
<aaaa></aaaa>
</div>
As #tymeJV said , you need to compile the html first and then call button() in directive controller
var app = angular.module("myApp", []);
app.directive('aaaa', function($compile) {
return {
restrict: 'E',
scope: {
data: '=',
//this is not working: button: function(){console.log('hello from button');}
},
link: function(scope, element) {
element.append('hello');
var htmlText = ' <button type="button" ng-click="button()">Click Me!</button> ';
var template = angular.element($compile(htmlText)(scope));
element.append(template);
},
controller: function($scope, $element){
$scope.button = function(){
console.log('button clicked');
}
}
}
});
I would advise to use angular templates instead of element.append, see example code below. Then you don't need all the compiler code 'n stuff.
You could also replace "template: 'hello
var app = angular.module("myApp", []);
app.directive('aaaa', function() {
return {
restrict: 'E',
scope: {
data: '='
},
link: function(scope, element) {
scope.button = function(){
console.log('hello from button');
};
},
template: 'hello <button type="button" ng-click="button()">Click Me!</button>'
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div ng-app="myApp">
<aaaa></aaaa>
</div>
you can out under link
link: function(scope, element) {
element.append('hello');
element.append(' <button type="button" ng-click="button()">Click Me!</button> ');
scope.button=function(){
//content goes here
}
}

Angular.js ng-repeat callback

I need to send a callback when ng-repeat finishes, but my solutions don't work. In my last solution I used a directive to do it.
Markup:
<div class="results" ng-model="results">
<div class="empl-card" ng-repeat="empl in employees | filter: searchQuery" callback-on-end="alert('callback')">
...
</div>
</div>
directive:
app.directive("callbackOnEnd", function() {
return {
restrict: "A",
link: function(scope, element, attrs) {
if (scope.$last) {
scope.$eval(attrs.callbackOnEnd);
}
}
};
});
Where could I have made a mistake?
I think you can do this with just ngInit as follows;
<div class="results" ng-model="results">
<div class="empl-card" ng-repeat="empl in employees | filter: searchQuery" ng-init="$last && alert('callback')">
...
</div>
</div>
You don't need a custom directive for doing this.
To achieve this you need to make a method in your controller and call that method when the ng-repeat ends :
(function() {
angular.element(document).ready(function() {
var app = angular.module('myApp', []);
app.controller("MyCtrl", function($scope, $timeout) {
$scope.names = ['A', 'B', 'C', 'D'];
$scope.onEnd = function() {
alert('all done');
};
});
app.directive("callbackOnEnd", function() {
return {
restrict: "A",
link: function(scope, element, attrs) {
if (scope.$last) {
scope.$eval(attrs.callbackOnEnd);
}
}
};
});
angular.bootstrap(document, ['myApp']);
});
}());
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-controller="MyCtrl" class="well">
<h3 ng-repeat="name in names" callback-on-end="onEnd()">{{name}}</h3>
</div>
Or you will have to eval the javascript code
app.directive("callbackOnEnd", function() {
return {
restrict: "A",
link: function(scope, element, attrs) {
if (scope.$last) {
eval(attrs.callbackOnEnd);
}
}
};
});
(function() {
angular.element(document).ready(function() {
var app = angular.module('myApp', []);
app.controller("MyCtrl", function($scope, $timeout) {
$scope.names = ['A', 'B', 'C', 'D'];
$scope.onEnd = function() {
alert('all done');
};
});
app.directive("callbackOnEnd", function() {
return {
restrict: "A",
link: function(scope, element, attrs) {
if (scope.$last) {
eval(attrs.callbackOnEnd);
}
}
};
});
angular.bootstrap(document, ['myApp']);
});
}());
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-controller="MyCtrl" class="well">
<h3 ng-repeat="name in names" callback-on-end="alert('done')">{{name}}</h3>
</div>
Find good explanation here :
https://stackoverflow.com/a/15671573/3603806
Check here. Created custom directive for repeatEnd
http://plnkr.co/edit/YhGzYFOcVaVds7iAEWPn?p=preview
<h3 ng-repeat="name in names" repeat-end="onEnd()">{{name}}</h3>
app.js
angular.element(document).ready(function() {
var app = angular.module('repApp', []);
app.controller("MainCtrl", function($scope, $timeout) {
$scope.names = ['user1', 'user2', 'user3'];
$scope.onEnd = function() {
$timeout(function() {
alert('all done');
}, 1);
};
});
app.directive("repeatEnd", function() {
return {
restrict: "A",
link: function(scope, element, attrs) {
if (scope.$last) {
scope.$eval(attrs.repeatEnd);
}
}
};
});
angular.bootstrap(document, ['repApp']);
});

ng-click not working on newly appended elements

Why is my ng-click not working when I appended it with a button? The same ng-click is working when I initially loaded the button.
app.controller('demoCtrl', function() {
this.clk = '<button ng-click="dctrl.click()">Button</button>';
this.click = function() {
alert('clicked');
}
})
app.directive('btnClick', function() {
return {
restrict: 'A',
scope: {
actionBtn: '='
},
link: function(scope, element, attrs) {
element.append(scope.actionBtn);
}
}
})
HTML
<body ng-controller="demoCtrl as dctrl">
<div btn-click action-btn="dctrl.clk"></div>
</body>
http://plnkr.co/edit/QPKXfGd9s7HzLvEfKvbG?p=preview
Update
I've also tried this way but no luck
element.append($compile(scope.actionBtn)(scope));
You need to compile an new dom element created manually for angularjs to work on it so
app.directive('btnClick', ['$compile', function ($compile) {
return {
restrict: 'A',
link: function (scope, element, attrs) {
element.append($compile(scope.$eval(attrs.actionBtn))(scope));
}
}
}])
var app = angular.module('my-app', [], function() {})
app.controller('demoCtrl', function() {
this.clk = '<button ng-click="dctrl.click()">Button</button>';
this.click = function() {
alert('clicked');
}
})
app.directive('btnClick', ['$compile',
function($compile) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
element.append($compile(scope.$eval(attrs.actionBtn))(scope));
}
}
}
])
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="my-app" ng-controller="demoCtrl as dctrl">
<div action-btn="dctrl.clk" btn-click></div>
</div>

How do I pass value directly into a directive?

I have a simple angular directive I would like to pass value to.
<div my-component binding-foo="foo">
<strong>get:</strong> {{isolatedBindingFoo}} // get it to output foo?
</div>
HTML
<div my-component binding='foo'> ... </div>
JS
yourApp.controller('yourController', ['$scope', function($scope) {
$scope.isolatedBindingFoo = '';
}])
.directive('myComponent', function() {
return {
controller: 'yourController',
scope: {
'binding': '=binding'
},
link: function($scope, $element, attrs) {
$scope.isolatedBindingFoo = attrs['binding'];
}
}
});
http://fdietz.github.io/recipes-with-angular-js/directives/passing-configuration-params-using-html-attributes.html
Cheers
AngularJS mangles HTML attributes to JS properties. eg, binding-foo in HTML will be mangled to bindingFoo in JS, and vice-versa
var myModule = angular.module('myModule', [])
.controller('yourController', ['$scope', function($scope) {
$scope.isolatedBindingFoo = '';
}])
.directive('myComponent', function() {
return {
restrict:'E,A',
controller: 'yourController',
scope: true,
link: function($scope, $element, attrs) {
$scope.isolatedBindingFoo = attrs['bindingFoo'];
}
}
});
http://jsfiddle.net/b2xo0o5u/3/
But in the example case this should be enough:
angular.module('myModule', [])
.directive('myComponent', function() {
return {
restrict:'EA',
scope: {
'isolatedBindingFoo': '#bindingFoo'
}
}
});
http://jsfiddle.net/b2xo0o5u/4/

AngularJS directive DOM manipulation not executing link()

Trying to do some DOM manipulation, but link() is never called so nothing happens:
app.js
var app = angular.module('app', ['directives', ...]);
var directives = angular.module('directives', []);
...
directives.js
directives.directive('doIt', ['$window', function($window) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
console.log('Inside link()');
// Do stuff with $window
}
};
]});
HTML
<html ng-app="app">
<body>
<div ng-view>
<div do-it>
// ....
</div>
</div>
</body>
</html>
What am I missing?
Your square bracket is incorrect
directives.directive('doIt', ['$window', function($window) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
console.log('Inside link()');
// Do stuff with $window
}
};
}]);//Check this part. The square bracket was on the wrong side of }
Move it like like I have it above
You also have some extra periods in your module decleration
var app = angular.module('app', ['directives']); //remove the extra ....'s
is this plnkr help?plnkr
angular.module('app', [])
// .controller('Controller', ['$scope', function($scope) {
// $scope.customer = {
// name: 'Naomi',
// address: '1600 Amphitheatre'
// };
// }])
.directive('doIt', ['$window', function($window) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
console.log('Inside link()');
// Do stuff with $window
}
};
}]);

Categories