如何动态地将angularjs ui bootstrap工具提示添加到现有标记?

时间:2014-01-31 21:15:46

标签: javascript jquery angularjs angular-ui-bootstrap

angularjs相对较新。帮助我理解这里发生了什么!

我最终要完成的任务:给定html中的文本块(比如段落元素),我想在文本中的选定单词中动态添加工具提示(准确地说是自举工具提示)。因此,例如,如果用户在搜索框中键入世界“hello”,则段落中的所有“hello”实例将在悬停时显示工具提示,显示某些消息,如定义或其他内容。

注意:我认为我最初并不清楚这一点,但是我要添加工具提示的文本块已经在html中,并且不会有任何类型的指令标记标记周围它。有关说明,请参阅我的fiddle

我在jQuery中完成了这个...现在我正试图让它在angularjs中工作!

我的第一次尝试是使用带有正则表达式的自定义过滤器,该过滤器会将带有工具提示属性的“a”标记插入到适当位置的段落中。新标记显示出来了,但似乎没有被angularjs“看到”(不太确定术语,但我认为它没有“绑定”??)。

这是jsfiddle上说明的问题:

http://jsfiddle.net/petersg5/pF33a/2/

(1)输出中的第一行在“foo”上有一个工作工具提示......它只是在标记中直接有工具提示属性。生成的html:

<a href="#" tooltip-placement="top" tooltip="basic tooltip" class="ng-scope">foo</a>

(2)第二行使用ng-bind-html,并且具有属性,但不是工作工具提示。生成的html:

<a href="#" tooltip-placement="top" tooltip="tooltip via ng-bind-html">foo</a>

(3)第三行使用过滤器,并具有属性,但不是工作工具提示。生成的html:

<a href="#" tooltip-placement="top" tooltip="tooltip via filter">foo</a>

我的主要问题是......如何解决我上面描述的任务?

次要问题是了解上述3个例子中的每个例子。我注意到(1)中的直接输出在生成的标记中有角度插入的“ng-scope”类。另外两个缺少这个,但确实在父p标签中插入了ng-binding类。不确定这里发生了什么,但我认为这与我的问题有关。

我觉得解决方案可能涉及指令,但我不确定如何将该指令应用于现有文本(即标记中已有的p标记)。

谢谢!

编辑:更新了jsfiddle以更准确地反映问题(输出中的第四行)

2 个答案:

答案 0 :(得分:17)

处理HTML的正确方法是使用angular指令,让我们制作一个带有两个参数的指令(比如dynamic-tooltip

  • 工具提示消息
  • 您的搜索字词

HTML

  <p dynamic-tooltip="my message" tooltip-element="searchElement">
    Hello World check out my foo bar app
  </p>

searchElement将与任何模型绑定,例如

  <input type="search" ng-model="search">
  <input type="button" value="Search" ng-click="searchElement = search">

当您点击search按钮时,您在搜索框中输入的值将设置为searchElement

指令定义是:

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);
        });
      }
    }
  })

指令$watch tooltip-element,因此当您更改值时,首先尝试删除以前的工具提示,然后尝试匹配您的search-word(如果找到),然后创建工具提示。< / p>

检查 Demo

答案 1 :(得分:3)

编辑:

我想我误解了你的要求了。特别是在注意到你已经使用了ui-boostrap角度模块之后。

我认为,问题在于,您附加的新属性不是由Angular编译的,因此tooltip指令永远不会运行。您需要通过$ compile(element)(范围)运行新附加的HTML / DOM。

指令示例。请注意,这不是完整的,将其视为伪代码而不是其他任何东西,但它应该作为如何做的指导。基本上,你可以在指令中使用你想要的任何jQuery,重要的是要注意你在链接函数中得到的'elem'与指令绑定的元素相同。此外,您需要在您创建的任何HTML / DOM上调用$ compile(your_element)(范围)并自行附加。

<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);
        }

    }

}])

这可能是一种天真的方法,但我并不完全了解您的要求。但它应该让你知道解决这个问题的可能方法。


我认为你正在以错误的方式解决问题。使用angular时有一个通用的规则,即:如果你正在修改DOM,你(几乎总是)需要一个指令。

那么,这里出了什么问题?

我对Bootstrap的工具提示实现不太熟悉,但我认为它永远不会选择新添加的“工具提示”属性。我相信它在第一个例子中起作用的原因是工具提示相关代码在页面加载时搜索DOM以获取工具提示属性,但在此之后添加它是不行(如果我错了请纠正我)。

那么,你怎么解决这个问题?

我相信你想以某种方式动态添加工具提示?我认为angular-ui bootstrap已经有支持这个的指令,例如ui-tooltip="{{variable.on.scope}}"。请参阅下面的链接。

或者,如果您还需要其他东西,则必须创建自己的指令。指令起初可能很吓人,但它们(在我看来)是Angular最重要的特性,一旦掌握它就很简单。

基本上,在创建新指令时,您可以在工具提示中传入定义所需文本的数据。在你的指令中的链接(范围,元素,attrs)函数内,你可以附加一个工具提示(使用Bootstrap的elem.tooltip()函数)到'elem',作为指令适用的元素。

如果您还需要附加<a>元素,则可以使用更高级的翻译。

如果您不熟悉指令,请阅读并询问您是否需要进一步的帮助。或者只是检查angular-ui-bootstrap(Bootstrap 3和2的版本): http://angular-ui.github.io/bootstrap/