I am trying to call a html page which is given in the templateUrl of my directive when I click a button, below is my code "hi" should be displayed when I click the "click me" button. Please suggest me how to do this.
sample.html:
<div ng-controller="MyController">
<button custom-click="">Click Me</button>
</div>
sample.js:
appRoot.directive('customClick', function() {
return {
link: function(scope, element, attrs) {
element.click(function(){
templateUrl:'/page.html';
});
}
}
});
Page.html:
<div><h4>HI</h4></div>
Update: The Snippet has been updated with getting the code from a URL
Adding onto the above answers:
appRoot.directive('customClick', function($http, $compile) {
return {
link: function(scope, element, attrs) {
element.click(function(){
$http.get("/page.html").then(function(resp){
$(element).html(resp.data);
var fnLink = $compile(element);
fnLink($scope);
});
});
}
}
});
P.S: Needs jQuery to run as using some functions like html() which can be bypassed if you dont want to include jQuery
I don't think that structure is possible, at all.
The easiest way would be to handle a show/hide type of functionality on the directive and have the template be there at all times.
For this you could use either ng-show, ng-hide or ng-if (and some others that I won't dig into).
base directive
appRoot.directive('customClick', function () {
return {
template: '<div><h5>HI</h5></div>',
link: function (scope, el, attrs) {
scope.active = false;
el.on('click', function () {
scope.$apply(function () {
scope.active = !scope.active;
});
});
}
}
});
ng-show
template: '<div ng-show="active"><h5>HI</h5></div>'
ng-hide
template: '<div ng-hide="!active"><h5>HI</h5></div>'
ng-if
template: '<div ng-if="active"><h5>HI</h5></div>'
Edit: If you are using templateUrl, simply put the ng-show/hide/if directive on the root element of the template being referenced, and this should work the same.
Oh, and here's a fiddle.
http://jsfiddle.net/ADukg/5426/
Related
I want to dynamically add ngClick to an attribute directive.
javascript
angular.module('app')
.directive('myDirective', ['$log', function ($log) {
return {
restrict: 'A', // PAY ATTENTION TO THIS LINE
compile: function (tElement) {
tElement.attr('ng-click', 'onClick()');
return function postLink(scope) {
scope.onClick = function () {
$log.debug('myDirective is clicked');
}
}
}
}
}]);
markup
<button my-directive>Click Me</button>
From the element inspector of Chrome, I can see that the ng-click attribute is added to the button.
I expect to see the text "myDirective is clicked." in the console when the button is clicked, but actually there's nothing printed. No error is raised. Anyone can help? Thanks in advance.
Rather than using link inside compile use the link function directly as shown below
link: function(scope, element, attrs) {
element.onClick(function(){
$log.debug('myDirective is clicked');
});
}
You can directly add the click handler to the element, you need not bind ng-click directive inside your directive.
Hello please try this one,
HTML:
<div ng-app="angularApp">
<div ng-controller="dirCtrl1">
<button ng-click="clickFun('clicked')">Button</button>
<button my-directive="directive">With directive</button>
</div>
</div>
JS:
.controller('dirCtrl1', function ($scope) {
$scope.clickFun = function (msg) {
console.log(msg);
};
})
.directive('myDirective', function(){
return{
restrict: 'A',
link: function(scope, ele, attr){
var eventName = attr.evetName || 'click';
var mas = attr.myDirective || 'just console';
ele.on(eventName, function(){
console.log(mas);
});
}
};
});
Let's say I have a "filterList" element. Inside is a list of <filter-item> angular directives. I want each <filter-item> to have a "delete" button inside of it. Clicking the delete button will remove the <filter-item> from the DOM.
How can I do this?
<div class="filterList">
<filter-item></filter-item>
<filter-item></filter-item>
<filter-item></filter-item>
</div>
FilterItem directive:
myApp.directive('filterItem', ['$http', function($http){
return {
scope: { },
replace: true,
link: function(scope, element, attrs){
scope.remove = function() {
// Hmm, I sure do wonder what goes here Mr Jones.
}
},
template: '<div>Hi mom! <button on-click="remove()">Remove</button></div>'
}
});
Inside of link you can do element.remove();.
Since AngularJS has jqLite, remove() removes the directive's element from the DOM. If your directive is not tied to any model, this is acceptable. Be careful manipulating the DOM like this when directives are rendered as a result of the model, since you haven't changed the model you can end up with strange effects (e.g. re-rendering).
(Self-answer but found a good post not on StackOverflow)
myApp.directive('filterItem', ['$http', function($http){
return {
scope: { },
replace: true,
link: function(scope, element, attrs){
scope.remove = function() {
element.remove();
}
},
template: '<div>Hi mom! <button on-click="remove()">Remove</button></div>'
}
});
method 1: i dont know if this is the right way to do it but you can use
<div class="filterList">
<filter-item></filter-item>
<filter-item></filter-item>
<filter-item></filter-item>
</div>
FilterItem directive:
myApp.directive('filterItem', ['$http', function($http){
return {
scope: {
hideDir:'=?'
},
replace: true,
link: function(scope, element, attrs){
scope.remove = function() {
// Hmm, I sure do wonder what goes here Mr Jones.
element.innerHTML='';
}
},
template: '<div>Hi mom! <button on-click="remove()">Remove</button></div>'
}
});
method 2: you can also try using ng-if and change variable inside directive
<div class="filterList" ng-if="!hideDir" hide-dir="hideDir">
<filter-item></filter-item>
<filter-item></filter-item>
<filter-item></filter-item>
</div>
FilterItem directive:
myApp.directive('filterItem', ['$http', function($http){
return {
scope: {
hideDir:'=?'
},
replace: true,
link: function(scope, element, attrs){
scope.remove = function() {
// Hmm, I sure do wonder what goes here Mr Jones.
scope.hideDir=true;
}
},
template: '<div>Hi mom! <button on-click="remove()">Remove</button></div>'
}
});
I am trying to change "Collapse" text to "Expand" on click of h2 tag. at the same time I am applying "active" class to h2 tag. using following directive, which is working fine, but now I am clueless about how to change "collapse" text to Expand on h2 tag click
HTML
<h2 class="panel-title" toggleclass>My Tandem URL</h2>
<a class="collapse-arrow">Collapse</a>
js
.directive("toggleclass", function () {
return {
restrict: 'A',
scope: false,
link: function (scope, element, attrs) {
element.bind("click", function () {
element.toggleClass('active');
});
}
}
})
Can anyone plz help..
The
If you want to do DOM manipulation in your directive you could change the contents of the element by doing:
var link = element.find('a');
link.text(link.text() === 'Collapse' ? 'Expand' : 'Collapse')`.
Using html instead of text also works.
You have to move the link inside the h2 to have the directive see the link.
Another approach is having the link text changed via the scope, but then you need to have a template and bind the link text to the directive scope. Then you have to wrap both elements in a directive.
This may make the solution a bit too big for this simple use case...
Another suggestion on making up an directive: encapsulates html and behaivor inside: fiddle .
angular.module('myModule', [])
.directive('togglable', function () {
return {
restrict: 'EA',
template: '<div><h2 class="panel-title" ng-class="{ active: isCollapsed }" ng-click="toggle()" ng-transclude></h2><a class="collapse-arrow">{{ isCollapsed ? "Expand" : "Collapse"}}</a></div>',
transclude: true,
replace: true,
scope: false,
controller: function ($scope) {
$scope.isCollapsed = false;
$scope.toggle = function () {
$scope.isCollapsed = !$scope.isCollapsed;
};
}
};
});
Key features:
- no manual DOM manipulaton;
- uses transclude feature;
Such a directive is easy to use:
<togglable>My Tandem URL</togglable>
Depending on how your app works, maybe you can try this:
HTML:
<h2 class="panel-title" ng-class="{'active': expand}" toggleclass>My Tandem URL</h2>
<a class="collapse-arrow" ng-hide="expand">Collapse</a>
<a class="collapse-arrow" ng-show="expand">Expand</a>
JS:
angular.module('myApp', [])
.controller('myCTRL', function($scope) {
$scope.expand = false;
})
.directive("toggleclass", function () {
return {
restrict: 'A',
scope: false,
link: function (scope, element, attrs) {
element.bind('click', function() {
scope.$apply(function() {
scope.expand = !scope.expand;
});
});
}
}
});
http://jsfiddle.net/uqbc9asf/
In this example, I have two AngularJS KendoDatePickers. The first one works perfectly, if you click on the button you open the calendar. The second one is within a directive that has the transclude attribute set to true. If you click on the second button, you get an error.
My understanding is that the scope of the transcluded portion inherits from the control scope, so this should work. Where am I wrong?
This is the plunk
HTML
<input kendo-date-picker="picker" />
<button ng-click="openPicker()">Open Date Picker</button>
<my-window>
<input kendo-date-picker="picker2" />
<button ng-click="openPicker2()">Open Date Picker 2</button>
</my-window>
Javascript
var app = angular.module("app", [ "kendo.directives" ]);
app.controller('MyCtrl', function($scope) {
$scope.openPicker = function () {
$scope.picker.open();
};
$scope.openPicker2 = function () {
$scope.picker2.open();
};
});
app.directive('myWindow', function() {
return {
transclude: true,
scope: {
someVar: '='
},
restrict: 'EA',
template: function(element, attrs) {
var html = '<div ng-transclude></div>';
return html;
}
};
});
There are two things about your code:
first: you create an isolatedScope so you do not have access to the controller scope inside the directive scope.
second: transcluded content get their own scope. One way to work around this is by not using transclude at all, like the example below:
return {
transclude: false,
restrict: 'EA',
template: function(element, attrs) {
var html = '<div>'+element.html()+'</div>';
return html;
}
or use the link function and manually transclude the element with the scope of the directive
Given this directive:
myApp.directive('someDirective', ['$compile', '$templateCache', function($compile, $templateCache) {
return {
restrict: 'A',
link: function(scope, element, attr) {
// Load a template.
var template = $templateCache.get("partials/foo.html");
$compile(template)(scope);
$(element).append(template);
}
};
}]);
and given foo.html:
<div data-foo>Some Text</div>
and the foo directive:
myApp.directive('foo', [function() {
return {
restrict: 'A',
link: function(scope, element, attr) {
console.log('foo1');
$(element).on('click', function() {
console.log('foo2');
});
}
};
}]);
I will always see foo1 in my console but never foo2 when I click on the added element. In fact, though I can see the added elements just fine and can console.log() them just fine, I am unable to ever bind any handlers to them. What am I missing?
A div will have no height unless you put something in it. Change your div to this:
<div data-foo>Some content</div>
Also you need to make the template an element, do this as well right after you create it:
template = angular.element(template);
Here's a jsFiddle showing you: http://jsfiddle.net/c3Wuu/
As a side note, you should not be wiring up a click event, or building a template like this. Have a look at some videos and do angular tutorial unless you know what you're doing.
Edit
This is how you would wire it up using angular practices
in foo directive html:
<div data-foo>
<span data-ng-click="clickOne()">Click One</span>
<span data-ng-click="clickTwo()">Click Two</span>
</div>
In foo link function:
scope.clickOne = function(){
console.log("click one");
};
scope.clickTwo = function(){
console.log("click two");
};
By wiring up your own click function you are circumventing the point of angular.