Directive inside bs-tooltip is not evaluated - angularjs

I am trying to have a <ul> element with its own directive (checkStrength) inside of an AngularStrap bs-tooltip title property, like this:
$scope.tooltip = {
title: '<ul id="strength" check-strength="pw"></ul>',
checked: false
};
The behavior I want is as follows: when a user clicks on the input textbox, a tooltip will appear showing the strength of the password as they enter it in the textbox.
This does not work, as shown in the two Plunkers below:
Custom "checkStrength" directive outside bs-tooltip works fine: Plunker
Custom "checkStrength" directive inside bs-tooltip does not work: Plunker

Ok, it doesn't appear that this is supported out of the box. You are going to have to create your own binding directive
Directive
.directive('customBindHtml', function($compile) {
return {
link: function(scope, element, attr) {
scope.$watch(attr.customBindHtml, function (value) {
element.html(value);
$compile(element.contents())(scope);
});
}
};
});
This go into Angular Straps code and make the follow modification on line 10 of tooltip.js in the plunker
Template
<div class="tooltip-inner" custom-bind-html="title"></div>
Then set the html property in the config to false.
Config
.config(function($tooltipProvider) {
angular.extend($tooltipProvider.defaults, {
html: false
});
})
Example: Plunker

Related

Angular directive for simple animation

I have a template, inside that template is div with the class big-box and it's inside a div container called .movie-container.
Template,
.movie-container
.big-box
I want to animate the .big-box element to a height of 300px (from 0px) when a user clicks on the .movie-container.
I've tried to setup a directive with a click function but it's not working. When I click on the .big-box div it doesn't show the click in the console log.
app.directive('big-box', [function() {
return {
link: function(scope, elem, attrs) {
elem.bind('click', function() {
console.log ('click')
});
}
}
}]);
So I could use some tips.
The naming convention used for the directive is not correct. You have to use camel case while defining your custom directives.
app.directive('bigBox', [function() { // Use camel case
return {
link: function(scope, elem, attrs) {
elem.bind('click', function() {
console.log ('click')
});
}
}
}]);
and in your html you need to use it like this :
<div class="movie-container">
<div big-box> <!-- using the directive -->
click here
</div>
</div>
The name must be written using dashes and each dash represents a capital letter from the directive definition. It is a angularjs convention.
Here is a working fiddle.

Using Qtip2 inside an Angular Directive Template

I am trying to use Qtip2 with Angular Directive Template.
Inside my Angular Directive Template are buttons and they are inside an angular ng-repeat loop.
And inside this ng-repeat loop, there is a unique variable called 'value' which is the name of each button.
So what I want is to use Qtip2 with this directive template that will display the 'value' tooltip.
The directive template looks something like this:
<button ng-mouseover="qtipping(value)"> {{value}} </button>
How do I implement this? I tried add an attribute to the button with a ng-mouseover="qtipping(value)" but it doesn't work.
The code inside my link function looks something like this:
link: function(scope,element,attrs){
scope.qtipping = function(value){
$("button").qtip({
content:{
text: value //This will appear the unique name of the button
}
})
}
}
When I run the code, basically nothing happens. I mouseover the buttons with nothing. No error too.
The code that works is:
link: function(scope,element,attrs){
$("button").qtip({
content:{
text: "TestMessage" //This will appear the unique name of the button
}
})
}
Without using a function. But I need a FUNCTION to extract the 'value' from the template dom. How do I go about doing this? I am also quite noob in Angular.
You should create a separate directive to show qtip on each button. Here is a directive to add qtip to an element:
.directive('qtip', function() {
return {
restrict: 'A',
link: function(scope, element, attrs) {
$(element).qtip({
content: {
text: attrs.qtipText
}
});
}
};
}
use it like this:
<button qtip qtip-text="{{value}}"> {{value}} </button>
EDIT: The code had a missing brace. Fixed that, here is a working plunker: http://plnkr.co/edit/uVdpf5gLILd82dr62V03?p=preview

Angular binding does not work in data- attribute

I am using some css html template that comes with many html components and with lots of data-attributes for various things. For example for slider it has something like
<div class="slider slider-default">
<input type="text" data-slider class="slider-span" value="" data-slider-orientation="vertical" data-slider-min="0" data-slider-max="200" data-slider-value="{{ slider }}" data-slider-selection="after" data-slider-tooltip="hide">
</div>
Here I am trying to bind the value
data-slider-value="{{ slider }}"
But it's not working. Variable 'slider' is set in the $scope as:
$scope.slider = 80;
Same value 80 shows up right when I bind it as:
<h4>I have {{ slider }} cats</h4>
I have also tried
ng-attr-data-slider-value="{{ slider }}"
It didn't work.
Update
The directive has something like this
function slider() {
return {
restrict: 'A',
link: function (scope, element) {
element.slider();
}
}
};
where element.slider(); calls the code in bootstrap-slider.js (from here) for each of the sliders.
I played with this for a while, and came up with a few options for you. See my Plunkr to see them in action.
Option 1: No need to update the scope value when the slider changes
This will work with the HTML from your question. The following is what you should change the directive code to.
app.directive('slider', function slider() {
return {
restrict: 'A',
link: function(scope, element, attrs) {
attrs.$observe('sliderValue', function(newVal, oldVal) {
element.slider('setValue', newVal);
});
}
}
});
Option 2: Two way binding to the scope property
If you need the scope property to be updated when the slider handle is dragged, you should change the directive to the following instead:
app.directive('sliderBind', ['$parse',
function slider($parse) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
var val = $parse(attrs.sliderBind);
scope.$watch(val, function(newVal, oldVal) {
element.slider('setValue', newVal);
});
// when the slider is changed, update the scope
// property.
// Note that this will only update it when you stop dragging.
// If you need it to happen whilst the user is dragging the
// handle, change it to "slide" instead of "slideStop"
// (this is not as efficient so I left it up to you)
element.on('slideStop', function(event) {
// if expression is assignable
if (val.assign) {
val.assign(scope, event.value);
scope.$digest();
}
});
}
}
}
]);
The markup for this changes slightly to:
<div class="slider slider-default">
<input type="text" data-slider-bind="slider2" class="slider-span" value="" data-slider-orientation="vertical" data-slider-min="0" data-slider-max="200" data-slider-selection="after" data-slider-tooltip="hide" />
</div>
Note the use of the data-slider-bind attribute to specify the scope property to bind to, and the lack of a data-slider-value attribute.
Hopefully one of these two options is what you were after.
I use .attr and it works for me. Try this:
attr.data-slider-value="{{slider}}"

scope.$watch in angular directive does not work proprely

I'm using Angular and Bootstrap.
I'm trying to replicate the functionality of ng-model for bootstrap checkbox. What i would like to accomplish is:
i would like that when i click on the checkbox (label really) the model change, and actually that works... but what does not work that when i try to watch the object for changes the behavior is weired, because i need two click insted of one for disable or enable the checkbox.
Moreover if inside the the label element that has as attribute cm-checkbox="model.prop" i put a {{model.anotherprop}} wont work (does not render anything).
From the documentation i understood that because i want the two-way data bind the scope must be defined as i did.
Thank you for your help!
I have the following HTML:
<label id="claim_free" class="checkbox" for="checkbox1" cm-checkbox="model.prop">
<span class="icons"><span class="first-icon fui-checkbox-unchecked"></span><span class="second-icon fui-checkbox-checked"></span></span><input name="claim_free" type="checkbox" value="" data-toggle="checkbox">
same lable text
</label>
And the following JS:
directive('cmCheckbox', function() {
return {
restrict: 'A',
scope: {'cmCheckbox':'='},
link: function(scope,elm,attrs) {
scope.$watch('cmCheckbox', function() {
console.log("first value for "+attrs.cmCheckbox+" is: "+scope.cmCheckbox);
if (!scope.cmCheckbox) {
console.log("checked");
$(elm).removeClass("checked");
$(elm).children("input").removeAttr("checked");
} else { // false and undefined
console.log("unchecked");
$(elm).addClass("checked");
$(elm).children("input").attr("checked","checked");
}
});
$(elm).on('click', function(e) {
e.preventDefault();
var currentValue = elm.hasClass("checked") ? false : true;
scope.$apply(function() {
scope.cmCheckbox = currentValue;
},true);
scope.$parent.$apply();
});
}
};
}).
Here is the jsFiddle: jsfiddle.net/pmcalabrese/66pCA/2

append template partial on click event in directive

I would like to be able to append a template from a partial on the click event of a button multiple times.
I've managed to add a div in the link function below, but I'm stuck. How do i replace it with a template?
Fiddle: http://jsfiddle.net/LPUZG/1/
app.directive('clicker', function($compile) {
'use strict';
return {
restrict: "A",
replace:false,
link: function(scope, element, attributes) {
element.bind("click", function(e){
element.parent().append('<div>hi</div>');
});
}
}
});
<div clicker>Click me</div>
EDIT: This partial contains some form input fields that will be filled out by the user and saved later on.
Thank you
Specifying template or templateUrl in a directive makes the directive replace the element with the content of the template. So your clicker div wont be in existence anymore.
Instead you can use ng-include:
<div ng-include="'partials/template.html'" ng-repeat="item in items"></div>
<!-- on click the add method adds to the items -->
<div ng-click="add()">Click Me To Add</div>

Resources