Ok, so it's fairly easy to create a directive for a colorbox, as explained here:
How to use Colorbox with Angular JS
But what if you want to then bind buttons to ng-click events? Best practice would suggest that the handler function for the action (delete in my case) should be in a directive defined on the controller. My colorbox directive looks like this:
mod.directive('colorbox', function() {
return {
restrict: 'A',
scope: true,
controller: function($scope, $element){
$scope.delete = function() {
console.log('I want this code to fire');
};
},
link: function (scope, element, attrs) {
$(element).colorbox({ inline: true, title: ' ', href: "#delconfirm", className: "delgroup", width: 450, height: 200, close: "" }, function() {
});
}
};
});
My template that will be loaded into the colorbox contains an action button with an ng-click:
<button ng-click="delete()">Delete</button>
However, that doesn't work. IF I move that delete function to my parent controller instead, and remove the controller from the directive, it then works. Any ideas why?
Related
I have following code
// Template
<span>
hello world!
</span>
// Directive
'use strict';
var referenceFieldTemplate = require('./reference-field.html');
module.exports = directiveFunction;
/* #ngInject */
function directiveFunction($http) {
return {
restrict: 'E',
scope: {
fieldName: '=',
fieldValue: '='
},
templateUrl: referenceFieldTemplate,
controller: function($scope){
console.log($scope);
},
link: function(scope, element, attr) {
element.bind('mouseover',function(e) {
console.log(e);
});
}
}
}
I'm trying to render custom directive in uib-tooltip using following code
function eventRender(event, element, view) {
var hoverMarkup = '\'<reference-field field-name="test" field-value="test"></reference-field>\''
element.attr({
'uib-tooltip-html': hoverMarkup,
'tooltip-append-to-body': true,
'tooltip-class': 'tooltip-wrapper'
});
$compile(element)($scope);
};
After compilation, the directive is not there in DOM. I want to understand the reason why it's not getting rendered. There are no errors in console.
Thanks in advance.
I've done recently something similar using "uib-tooltip-template", put all your html code inside the template and it will work just fine.
You just need to create a html file with your directive inside and asign it via $scope to the tooltip.
I am trying to add $watch in my directive. The directive is for wizard creation , when I read an existing array and use ng-repeat in directive it works as expected but If I update my array the newly added items in array doesn't add in directive to create wizard.
Please refer This plunker to understand the issue. At this plunker script.js has array data which I will be updating on a button click and read them back in ng-repeat under wizard directive on html page.
the directive is
directive('wizard', function($timeout, $compile) {
var opts = {
headerTag: "h3",
bodyTag: "section",
transitionEffect: "slideLeft",
autoFocus: true,
enableAllSteps: true,
enableKeyNavigation: false,
enableCancelButton: true,
enableFinishButton: true,
showFinishButtonAlways: false
};
return {
restrict: 'E',
replace: true,
template: '<div class="mywizard"></div>',
compile: function (tEl) {
return function(scope, element, attrs, ngModel) {
var stepsEl;
element.wrapInner('<div class="steps-wrapper">');
element.children('.steps-wrapper').append(tEl.context.innerHTML);
var content = $compile(element.contents())(scope);
$timeout(function () {
element.children('.steps-wrapper').steps(opts);
})
}
}
};
});
Please share idea where should I apply the watch.
I have an isolated scope directive that is called when I click on a button, this directive passes all the scope attrs to a element.bind('click' that opens a fancybox (to show a modal), the problem am having is when fancybox opens and a link is clicked, if I put a onclick event on that anchor, it never fires, it says the function is undefined even though is right there within the directive definition. I don't get it, what is wrong??
Here is an example:
search.directive('popup', [ function () {
return {
scope: {
content: '#',
expiration: '#',
instructions: '#'
},
restrict: 'A',
controller: function($scope, $element) {
function hello() {
alert('hello richie');
}
var attr = '<a onclick="hello();" href="google.com">' + $scope.content + '</a>';
$element.bind('click', function() {
$.fancybox.open({
modal : false,
maxWidth : 800,
maxHeight : 600,
fitToView : false,
autoSize : true,
content: attr,
closeClick : false,
openEffect : 'none',
closeEffect : 'none',
helpers: {
overlay: {
locked: false
}
},
tpl : {
closeBtn : '<button type="button" class="fancybox-item fancybox-close close my-own-close">×</button>'
}
});
});
I'm not familiar with the fancybox class you're using, but I'm guessing you'll need to call $compile on your html prior to setting it as the content, otherwise it is just raw HTML and it will have no angular context. So it will be looking for a global function called hello() which doesn't exist.
I've searched the internet long and hard and found no straight answer. My question is simple, I want to have something like this in my markup:
<div my-tooltip-template="'mytt.tpl.html'" my-tooltip-scope="myDataItem">Some text...</div>
EDIT: Where myDataItem is a scope variable which contains my data object, and with a template which might look like:
<h1>{{dataItem.title}}</h1>
<span>{{dataItem.description}}</span>
And I want to have that template compiled with the a scope which contains myDataItem as dataItem and displayed as a tooltip. As far as I could tell by experimenting with ui-bootstrap tooltip module, the way to inject html into a tooltip is by using the directive tooltip-html-unsafe but the html injected doesn't get compiled, i.e., angular expressions are not evaluated, directives are not expanded, etc.
How do I go about creating a directive for this? I want a lean result, I don't want to have to include jQuery or any other library, just AngularJS and ui-bootstrap.
Thanks a lot!
Here're the blueprints of how you could create a tooltip according to your requirements (or modify/encorporate this with ui-bootstrap's tooltip).
app.directive("myTooltipTemplate", function($compile){
var contentContainer;
return {
restrict: "A",
scope: {
myTooltipScope: "="
},
link: function(scope, element, attrs, ctrl, linker){
var templateUrl = attrs.myTooltipTemplate;
element.append("<div ng-include='\"" + templateUrl + "\"'></div>");
var toolTipScope = scope.$new(true);
angular.extend(toolTipScope, scope.myTooltipScope);
$compile(element.contents())(toolTipScope);
}
};
});
This, of course, doesn't have any of the actual tooltip functionality, like popup, placement, etc... - it just appends the compiled template to whatever the element that this directive applies to.
Plunker
Changed plunker with closer-to-tooltip behavior;
I was able to just copy and override the directive for the tooltip-html-unsafe
angular.module( 'ui.bootstrap.tooltip')
.directive( 'tooltipSpecialPopup', function () {
return {
restrict: 'EA',
replace: true,
scope: { content: '#', placement: '#', animation: '&', isOpen: '&' },
templateUrl: 'tooltip.tpl.html'
};
})
.directive( 'tooltipSpecial', [ '$tooltip', function ( $tooltip ) {
return $tooltip( 'tooltipSpecial', 'tooltip', 'mouseenter' );
}]);
I just changed the unsafe bit to special in the directive name and changed the template.
Here's a Plunker
I found this question searching for a classic tooltip implementation in AngularJS, jQuery (and other libraries) free.
I have built the following directive if anyone is searching for one:
app.directive('tooltip', function($sce, $compile) {
return {
restrict: 'A',
scope: {
content: '=tooltipContent'
},
link: function(scope, element, attributes) {
/* Attributes */
scope.displayTooltip = false;
/* Methods */
scope.updateTooltipPosition = function(top, left) {
tooltip.css({
top: top + 'px',
left: left + 'px',
});
};
scope.getSafeContent = function(content) {
return $sce.trustAsHtml(content);
};
/* Bootstrap */
var tooltip = angular.element(
'<div ng-show="displayTooltip" class="tooltip">\
<span ng-bind-html="getSafeContent(content)"></span>\
</div>'
);
angular.element(document.querySelector('body')).append(tooltip);
/* Bindings */
element.on('mouseenter', function(event) {
scope.displayTooltip = true;
scope.$digest();
});
element.on('mousemove', function(event) {
scope.updateTooltipPosition(event.clientY + 15, event.clientX + 15);
});
element.on('mouseleave', function() {
scope.displayTooltip = false;
scope.$digest();
});
/* Compile */
$compile(tooltip)(scope);
}
};
});
You can test it here: http://jsfiddle.net/m4sr9jmn/2/
Hope it will help !
I am trying to load a 'class' directive using ng-class. but my directive is never loaded when i do that. The directive is a multipurpose directive, and I don't want to create an isolated scope on this. it will be loaded only when required, based on ng-class conditions hence not using attribute or element directive. has anyone tried doing this and succeeded?
this directive is called using <div ng-class="someClass {{tooltip: enabled}}"></div>
here enabled is a scope variable.
app.directive('tooltip', ['$timeout', '$location', '$rootScope', function (timer, $location, $rootScope) {
return {
restrict: 'C',
transclude: true,
link: function (scope, element) {
var printContent = function () {
/* uses the content of .tooltip-content if it is a complex html tooltip,
otherwise
you can use the title attribute for plaintext tooltips
*/
var tooltipContent = $(element).find('.tooltip-content').html();
if (!tooltipContent) {
tooltipContent = $(element).attr('title');
}
$(element).tooltip({
content: tooltipContent,
items: "img, a, span, button, div",
tooltipClass: "tooltip",
position: { my: "left+30 top", at: "right top", collision: "flipfit" },
show: { effect: "fadeIn", duration: "fast" },
hide: { effect: "fadeOut", duration: "fast" },
open: function (event, ui) { $rootScope.tooltipElement = event.target; }
});
};
timer(printContent, 0);
}
};
}]);
Interesting issue. It seems that you don't want to use the ng-class directive since that doesn't recompile the content after adding the class. You'll likely want to create your own dynamic-class directive that actually recompiles when the value is true:
app.directive('dynamicClass', function($compile) {
return {
scope: {
dynamicClassWhen: '=',
dynamicClass: '='
},
link: function(scope, elt, attrs) {
scope.$watch('dynamicClassWhen', function(val) {
if (val) {
console.log(val);
elt.addClass(scope.dynamicClass);
$compile(elt)(scope);
}
});
}
};
});
You may need to modify this for the ability to remove the class and depending on if the $compile is sufficient for you or if you need to further manipulate the html, but this seems to be the right track for you. I made a fiddle with this in action.
Hope this helps!