how to call the directive on button click inside custom directive - angularjs

Hi i am working on custom directives of angularjs. I just want to know that how to call the directive when I click the button. Please suggested me how to achieve this.
Thanks

<div ng-controller="ctrl">
<mydirc></mydirc>
<button ng-click="clickMe()">call clickMe()</button>
</div>
app.directive('mydirc', function() {
return {
restrict: 'E',
replace: true,
template: '<div></div>',
link: function($scope, element, attrs) {
$scope.clickMe= function() {
alert('inside click');
}
}
}
});

The following example shows a sample custom directive which can handle click events; This is a scope-independent directive. And the appRoot module has to be defined earlier.
<div ng-controller="MyController">
<button custom-click="">Click Me</button>
</div>
appRoot.directive('customClick', function() {
return {
link: function(scope, element, attrs) {
element.click(function(){
//Do something useful
});
}
}
});

By "calling" the directive I am going to assume you mean handling the onclick event from the directive.
You can leverage the 'link' property of directives to attach scope initialization and functions like so:
http://jsbin.com/moruyoso/2
HTML
<!DOCTYPE html>
<html ng-app='app'>
<head>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.14/angular.min.js"></script>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body>
<div clicker></div>
</body>
</html>
JS
var app = angular.module('app', []);
app.directive('clicker', function(){
var link = function(scope){
scope.showMessage = function(){
alert('you clicked the directive!');
};
};
return{
link: link,
template: "<button ng-click='showMessage()'>Click me!</button>"
};
});

This example shows how to handle a click event for more than one button inside a directive:
Java Script: ( app.js )
angular.module('app', [])
.controller("articles.controller", function(){
var viewModel = this;
viewModel.articles =
[
{
title: "PHP",
content: "content 1",
selected: false
},
{
title: "C#",
content: "content 2",
selected: false
}
];
viewModel.addArticle = function(){
viewModel.articles.push(
{
title: "MySQL",
content: "new content",
selected: false
}
);
};
viewModel.select = function(article){
article.selected = !article.selected;
};
viewModel.getAll = function(){
console.clear();
console.log(viewModel.articles);
};
viewModel.getSelected = function(){
console.clear();
angular.forEach(viewModel.articles, function(article, key){
if(article.selected)
{
console.log(article.title);
}
});
};
})
.directive("artilceTile", function(){
return {
restrict: 'E',
scope: {
article: '='
},
link: function(scope, element, attr)
{
scope.displayTitle = function()
{
alert(scope.article.title);
},
scope.displayContent = function()
{
alert(scope.article.content);
},
scope.inverseArticleStatus = function()
{
scope.article.selected = !scope.article.selected;
}
},
template: `
<h1>{{article.title}}</h1>
<p>{{article.content}}</p>
<p ng-if="article.selected">Selected</p>
<input ng-model=article.title>
<button ng-click="displayTitle()">Dispaly Title</button>
<button ng-click="displayContent()">Display Content</button>
<button ng-click="inverseArticleStatus()" ng-if="!article.selected">Select</button>
<button ng-click="inverseArticleStatus()" ng-if="article.selected">Unselect</button>
<br><br><br><hr>
`
};
});
HTML: ( index.html )
<!DOCTYPE html>
<html ng-app="app">
<head>
<title></title>
</head>
<body>
<div ng-controller="articles.controller as articlesController">
<span ng-repeat="article in articlesController.articles">
<artilce-tile article="article"></artilce-tile>
</span>
<br><br>
<button ng-click="articlesController.addArticle()">Add New Article</button>
<button ng-click="articlesController.getSelected()">Get Selected Articles</button>
<button ng-click="articlesController.getAll()">Get All Articles</button>
</div>
<script type="text/javascript" src="angular.js"></script>
<script src="app.js"></script>
</body>

If you mean to ask how to show a directive template on button click, use a variable in the controller scope to show/hide it and update the variable on button click.
<div ng-controller="ctrl">
<mydirc ng-show="showMydirc"></mydirc>
<button ng-click="clickMe()">call clickMe()</button>
</div>
app.controller("ctrl", function($scope){
$scope.showMydirc=false;
$scope.clickMe = function(){
$scope.showMydirc = true;
}
});

Related

Unable to change the Parent Scope variable from Directive scope using two way binding

I am trying to create a custom directive which takes a username as an input. It then validates and checks if the username is available or not. If the username is not available I want to pass some values back to the parent Controller.
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="utf-8">
<title>AngularJS Isolate Scope</title>
</head>
<body>
<div ng-app="mainApp">
<div ng-controller="AppCtrl">
<div> From Controller : <input type="text" ng-model="ctrlRole"></div><br>
{{parentVariable}}
<input type="text" is-unique="{url: 'http://WWW.GOOGLE.COM'}" ng-model="role"/>
</div>
</div>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
<script>
var app = angular.module('mainApp', []);
app.controller("AppCtrl", function($scope){
$scope.ctrlRole = "Development";
$scope.parentVariable = "a";
});
app.directive("isUnique", function() {
return {
restrict : 'A',
require : 'ngModel',
transclude: 'true',
scope:{
parentVariable:"="
},
link : function(scope, element, attrs, ngModel) {
element.bind('blur', function (e) {
if (!ngModel || !element.val()) return;
var keyProperty = scope.$eval(attrs.isUnique);
console.log('this is the keyProperty we have received from the front end ' + keyProperty.url);
var currentValue = element.val();
console.log('this is the data we are going to validate ' + currentValue);
if(currentValue == 'AE'){
console.log('Changing the value ');
scope.parentVariable = 'b';
}
});
}
}
});
</script>
</body>
In summary I am trying to change the value of parentVariable from the directive scope depending on some conditions but its not happening, please let me know what I am doing wrong.
You specify the isolate scope parameter parentVariable, but in the template there is no value passed to it:
<input type="text" is-unique="{url: 'http://WWW.GOOGLE.COM'}" ng-model="role"/>
You would need:
<input type="text" is-unique="{url: 'http://WWW.GOOGLE.COM'}" parent-variable="parentVariable" ng-model="role"/>
Here, is an isolated example.
var app = angular.module('test', []);
app.controller('MainCtrl', function($scope) {
$scope.foo = 'foo';
});
app.directive('testDir', function($timeout) {
return {
restrict: 'A',
scope: {
val: '='
},
link: function(scope) {
console.log(scope.val);
$timeout(function() {
scope.val = 'bar';
}, 1000);
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="test">
<div ng-controller="MainCtrl">
{{foo}}
<div test-dir val="foo"></div>
</div>
</div>

AngularJS How to add / remove directive dynamically in page when button click

suppose i have two button and when we click on button 1 then show function call in controller and same way when we click on button 2 then hide function call in controller.
from show function how could i dynamically load and add directive in page and as well as how could i hide or remove directive from page when hide function will be called.
hence i am new in angular so not sure the below code will add directive at run time if i call it from show function ?
$('body').append($compile("<my-angular-directive />")(scope));
scope.$apply();
i do not know how to remove directive from page if it exist in page from controller function. give me suggestion how to achieve this. thanks
you can use directive as class and you can load it with ng-class directive
var jimApp = angular.module("mainApp", []);
jimApp.controller('mainCtrl', function($scope){
$scope.showMyDir = true;
$scope.buttonClcik = function(){
$scope.showMyDir = !$scope.showMyDir;
};
});
jimApp.directive("customDir1", function() {
return {
restrict:"AEC",
scope:{
value:"="
},
link: function(scope, element, attrs) {
}
}
});
jimApp.directive("customDir2", function() {
return {
restrict:"C",
link: function(scope, element, attrs) {
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.3/angular.min.js"></script>
<div ng-app="mainApp" ng-controller="mainCtrl">
<button ng-click="buttonClcik();">Click</button>
<div ng-class="{'custom-dir1': showMyDir, 'custom-dir2': !showMyDir}" value="showMyDir">Hai</div>
</div>
Use ng-if. So basically if you have a scope variable let's say $scope.showElement you can then use it like this:
In your controller:
$scope.showElement = true;
HTML:
<this-directive ng-if="showElement"></this-directive>
Originally the directive will show up but when you change the value of $scope.showElement it will be removed.
EDIT based on your comment:
Set your $scope.showElement to false and on ng-click set it to true like this:
angular.module('myApp', [])
.controller('testController', function($scope) {
$scope.showElement = false;
$scope.toggleElement = function() {
console.log('toggle element');
$scope.showElement = $scope.showElement ? false : true;
};
});
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular.min.js"></script>
</head>
<body ng-controller="testController">
<button type="button" ng-click="toggleElement()">Show directive</button>
<div ng-if="showElement" style="width:100%;height:40px;background-color:red;">This element will be shown/removed</div>
</body>
</html>
EDIT 2:
You can also use css declarations for better performance if you don't mind that the element still stays on the page but is hidden. With css it would go like this:
angular.module('myApp', [])
.controller('testController', function($scope) {
$scope.showElement = false;
$scope.toggleElement = function() {
console.log('toggle element');
$scope.showElement = $scope.showElement ? false : true;
};
});
.hidden {
display: none;
}
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.9/angular.min.js"></script>
</head>
<body ng-controller="testController">
<button type="button" ng-click="toggleElement()">Show directive</button>
<div ng-class="{'hidden' : showElement === false}" style="width:100%;height:40px;background-color:red;">This element will be shown/removed</div>
</body>
</html>
You could easily use ng-if directive on the wrapper of your custom directive
<div ng-if="showMyDir()">
<my-angular-directive />
</div>
<div ng-if="showMyDirTwo()">
<my-angular-directive-two />
</div>

Dynamic src with include-replace

I used this solution to replace root node with template and it was ok. But then it was necessary to change template url dynamically. In this case previous template remains on page and new template adds after it on template url changing. Is it possible to avoid this behavior somehow? I still need to replace root element because of makeup troubles.
angular.module("app", [])
.directive('includeReplace', function() {
return {
require: 'ngInclude',
restrict: 'A',
link: function(scope, el, attrs) {
el.replaceWith(el.children());
}
};
})
.controller("MainController", function() {
this.tpl = "tpl1.html";
this.toggle_tpl = function() {
this.tpl = (this.tpl == 'tpl1.html') ? 'tpl2.html' : 'tpl1.html';
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<div ng-controller="MainController as mCtrl">
<script type="text/ng-template" id="tpl1.html">
<div>First template</div>
</script>
<script type="text/ng-template" id="tpl2.html">
<div>Second template</div>
</script>
<button ng-click="mCtrl.toggle_tpl()">toggle</button>
<div ng-include="mCtrl.tpl" include-replace>
</div>
</div>
</div>
Try .html() instead of .replaceWith()
angular.module("app", [])
.directive('includeReplace', function() {
return {
require: 'ngInclude',
restrict: 'A',
link: function(scope, el, attrs) {
el.html(el.children().html()); // My changes in the line
}
};
})
.controller("MainController", function() {
this.tpl = "tpl1.html";
this.toggle_tpl = function() {
this.tpl = (this.tpl == 'tpl1.html') ? 'tpl2.html' : 'tpl1.html';
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<div ng-controller="MainController as mCtrl">
<script type="text/ng-template" id="tpl1.html">
<div>First template</div>
</script>
<script type="text/ng-template" id="tpl2.html">
<div>Second template</div>
</script>
<button ng-click="mCtrl.toggle_tpl()">toggle</button>
<div ng-include="mCtrl.tpl" include-replace>
</div>
</div>
</div>

Alert directive not showing after it has been rendered once

I have a directive to display an alert message every time a post call succeeds/fails. The alert for the first post always succeeds but if I close the alert, and trigger another post the alerts don't show anymore.
Some code below:
Include tag in html
<alert message="notification"></alert>
Directive
app.directive("alert", function(){
return{
restrict: 'EA',
templateUrl: "alert.html",
replace: false,
transclude: false,
scope: {
message: "=",
close: "&"
},
link: function(){
}
};
});
Template
<div class="alert alert-{{message.type}}" ng-show="message.text">
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
<div>{{message.text}}</div>
</div>
UPDATE: http://plnkr.co/edit/mECmQNSgW0EdXZGPmkNx?p=preview
Any thoughts?
Thanks in advance.
Instead of using data-dismiss="alert" you can have your close button call the close function. The close function can then clear the notifications since you have $scope.notification in the isolated scope as scope.message:
var app = angular.module('app', []);
app.controller('AlertDemoCtrl', function($scope) {
$scope.notification = {};
$scope.alertNotif = function() {
$scope.notification.type = "error";
$scope.notification.text = "demo text";
};
});
app.directive("alert", function() {
return {
restrict: 'EA',
template: '<div class="alert alert-{{message.type}}" ng-show="message.text">' +
'<button type="button" class="close" ng-click="close()" aria-hidden="true">×</button>' +
'<div>{{message.text}}</div>' +
'</div>',
replace: false,
transclude: false,
scope: {
message: "=",
close: "&"
},
link: function(scope) {
scope.close = function() {
scope.message = {};
}
}
};
});
<!DOCTYPE html>
<html ng-app="app">
<head>
<!-- jQuery -->
<script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.4/angular.js"></script>
<script src="script.js"></script>
</head>
<body>
<div ng-controller="AlertDemoCtrl">
<button ng-click="alertNotif()">test</button>
<alert message="notification"></alert>
</div>
</body>
</html>
Per the Bootstrap documentation (emphasis mine):
… Closing an alert removes it from the DOM.
Because it's removed from the DOM it will not show up again...

Angular Strap. Popover programmatic use

I'm trying to create programmatically popover, but faced with following problem. I can't access parent scope inside popover template. Expected result is:
Hello my name is Roman
but I get
Hello my name is undefined
Here is plunker
If I use bs-popover as attribute on any element, then I get expected result.
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
<title>Popover issue</title>
</head>
<body>
<div data-ng-app="myApp" data-ng-controller="defaultCtrl" style="margin: 100px 100px">
<button custom-popover ng-click="showPopover()">Popover</button>
<script type="text/ng-template" id="example.html">
<p>My name is {{user.name || 'undefined' }}</p>
</script>
</div>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.5/angular.min.js"></script>
<script src="//code.angularjs.org/1.3.8/angular-sanitize.min.js" data-semver="1.3.8"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-strap/2.1.5/angular-strap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-strap/2.1.5/angular-strap.tpl.min.js"></script>
<script type="text/javascript">
var app = angular.module("myApp", ['mgcrea.ngStrap', 'ngSanitize']);
app.controller("defaultCtrl", ["$scope", function($scope) {
$scope.user = {
name: "Roman"
};
}]);
app.directive("customPopover", ["$popover", "$compile", function($popover, $compile) {
return {
restrict: "A",
scope: true,
link: function(scope, element, attrs) {
var myPopover = $popover(element, {
title: 'My Title',
contentTemplate: 'example.html',
html: true,
trigger: 'manual',
autoClose: true
});
scope.showPopover = function() {
myPopover.show();
}
}
}
}]);
</script>
</body>
</html>
Thanks in advice
Checkout http://plnkr.co/edit/62BDv7JwluOl3eqtXPCZ?p=preview
Prototype inheritance is default on scope in angular.
So if you are not creating isolated scope then you can access parent scope objects from your scope directly until and unless you are not overriding them.
var myPopover = $popover(element, {
title: 'My Title',
contentTemplate: 'example.html',
html: true,
trigger: 'manual',
autoClose: true,
scope: scope
});
scope.showPopover = function() {
myPopover.show();
}

Resources