Relatively new to angularjs. Help me understand what\'s going on here!
What I\'m ultimately trying to accomplish: Given a block of text in my html (say in a paragraph e
EDIT:
I think I misunderstood your requirement a bit. Especially after noticing that you use ui-boostrap angular module already.
Problem here, I would think, is that the new attributes you attach are not compiled by Angular, hence the tooltip
directive is never run. You need to run the newly attached HTML/DOM through $compile(element)(scope).
Directive example. Please note that this isn't complete, treat it more as pseudocode than anything else, but it should serve as a guideline for how to do it. Basically, you can use whatever jQuery you want inside the directive, important thing to note is that the 'elem' you get in the link function is the same element which the directive is bound to. Also, you need to call $compile(your_element)(scope) on any HTML/DOM you create and attach yourself.
<p tooltip-tag="the_tag" text="My tooltip text">This is my tooltip the_tag test</p>
myApp.directive('tooltipTag', ['$compile', function($compile) {
return {
scope: {
text: '@' // Create isolate scope as this is a reusable component, we don't want to clutter parent scope
},
link: function(scope, elem, attrs) {
// Elem is here the <p> element, as jqLite/jQuery element.
// Put whatever logic you want here, feel free to use jQuery if you want
// I guess you want to copy out the text, search for 'the_tag' (which you can find in 'attrs.tooltipTag') in the text inside the <p></p> and then replace the content.
// Replace content elem.
elem.html(replaced_html); // Contains text with the_tag replaced with <a href="whatever" tooltip="{{text}}" etc..>the_tag</a>
var to_compile = elem.children('a');
// Finally, compile and attach to scope with
$compile(to_compile)(scope);
}
}
}])
This is probably a naive approach, but I don't fully know your requirements. But it should give you an idea of a possible way to solve this.
I think you are approaching the problem the wrong way. There is a general rule when using angular, which is: If you're modifying the DOM, you (almost always) need a directive.
I'm not too familiar with Bootstrap's tooltip implementation, but I would assume it never picks up the newly added 'tooltip' attributes. I believe the reason it works in the first example is that tooltip related code search the DOM for tooltip attributes upon page load, but adding it after that is a no go (please correct me if I'm wrong).
I believe you want to add tooltips dynamically somehow? I think angular-ui bootstrap already have directives supporting this, e.g. ui-tooltip="{{variable.on.scope}}"
. See link further down.
Or, if you need something else, you have to create your own directive. Directives might be scary at first, but they're (in my opinion) the most important feature of Angular and pretty simple to use once you get the hang of it.
Essentially, when creating a new directive, you can pass in data defining the text you want in the tooltip. Inside the link(scope, elem, attrs) function in your directive, you can attach a tooltip (using Bootstrap's elem.tooltip() function) to the 'elem', being the element the directive applies to.
If you need to attach the <a>
element as well, you can use transclusion, which is a bit more advanced.
If you're not familiar with directives, please read up on it and ask if you need further help. Or just check out angular-ui-bootstrap (there are versions for both Bootstrap 3 and 2): http://angular-ui.github.io/bootstrap/
The proper way to handle HTML
would be angular directive, lets make a directive (say dynamic-tooltip
) that takes two parameter
In HTML
<p dynamic-tooltip="my message" tooltip-element="searchElement">
Hello World check out my foo bar app
</p>
The searchElement
will be bind with any model like
<input type="search" ng-model="search">
<input type="button" value="Search" ng-click="searchElement = search">
Here when you click search
button, the value you typed in search box will be set in searchElement
The directive definition is:
app.directive('dynamicTooltip', function($compile) {
return {
restrict: 'A',
scope: {
tooltipElement: '=',
dynamicTooltip: '@'
},
link: function(scope, element, attrs) {
var template = '<a href="#" tooltip-placement="top" tooltip="' + scope.dynamicTooltip + '">{{tooltipElement}}</a>';
scope.$watch('tooltipElement', function(value) {
var previousTooltip = element.find('a');
angular.forEach(previousTooltip, function(item, i) {
var el = angular.element(item);
el.replaceWith(el.text());
});
var searchText = scope.tooltipElement;
if (searchText) {
replaced = element.html().replace(new RegExp(searchText, "g"), template);
element.html(replaced);
}
$compile(element.contents())(scope);
});
}
}
})
The directive $watch
tooltip-element
, so when you change the value, first it try to remove previous tooltips then it try to match your search-word
if found any then create the tooltip.
Check the Demo