Подтвердить что ты не робот

Как добавить динамические всплывающие подсказки angularjs ui к существующей разметке?

Относительно новый для угловых. Помогите мне понять, что происходит здесь!

То, что я в конечном счете пытаюсь выполнить: Учитывая блок текста в моем html (скажем, в элементе абзаца), я хочу динамически добавлять всплывающие подсказки (точнее, всплывающие подсказки) для выбранных слов в тексте. Например, если пользователь вводит мир "привет" в окно поиска, все экземпляры "привет" в абзаце будут отображать всплывающую подсказку при наведении курсора, отображая какое-то сообщение как определение или что-то в этом роде.

ПРИМЕЧАНИЕ. Я не думаю, что это было изначально изначально, но блок текста, к которому я хочу добавить всплывающую подсказку, уже находится в 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>

Мой главный вопрос: как решить задачу, описанную выше?

Вторичный вопрос - это понимание того, что происходит в каждом из приведенных выше примеров. Я заметил, что прямой вывод в (1) имеет класс "ng-scope", вставленный angular в сгенерированную разметку. Другим двум недостает этого, но у них есть класс привязки ng, вставленный в родительский тег p. Не уверен, что происходит здесь, но я думаю, что это имеет какое-то отношение к моей проблеме.

У меня такое чувство, что решение может включать директиву, но я не уверен, как применить эту директиву к существующему тексту (т.е. тег p уже в разметке).

Спасибо!

EDIT: обновил jsfiddle, чтобы более точно отразить проблему (четвертая строка на выходе)

4b9b3361

Ответ 1

Правильный способ обработки 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, если он найден, затем создайте всплывающую подсказку.

Проверьте Демо

Ответ 2

EDIT:

Я думаю, что неправильно понял ваше требование. Особенно после того, как вы заметили, что уже используете модуль ui-boostrap angular.

Проблема здесь, я думаю, заключается в том, что новые атрибуты, которые вы прикрепляете, не скомпилированы Angular, поэтому директива tooltip никогда не запускается. Вам нужно запустить недавно присоединенный HTML/DOM через компиляцию (элемент) (область).

Пример директивы. Обратите внимание, что это не является полным, рассматривайте его скорее как псевдокод, чем что-либо еще, но оно должно служить ориентиром для того, как это сделать. В принципе, вы можете использовать любой jQuery, который вы хотите в директиве, важно отметить, что "elem", который вы получаете в функции ссылок, - это тот же самый элемент, к которому привязана директива. Кроме того, вам нужно вызывать $compile (your_element) (область) на любом HTML/DOM, который вы создаете и присоединяете.

<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 и довольно просты в использовании, когда вы ее повесили.

По сути, при создании новой директивы вы можете передавать данные, определяющие текст, который вы хотите в всплывающей подсказке. Внутри ссылки (scope, elem, attrs) функция в вашей директиве, вы можете прикрепить всплывающую подсказку (используя функцию Bootstrap elem.tooltip()) к элементу, являющемуся элементом, к которому применяется директива.

Если вам нужно также добавить элемент <a>, вы можете использовать переход, который немного более продвинут.

Если вы не знакомы с директивами, прочитайте об этом и спросите, нужна ли вам дополнительная помощь. Или просто проверьте angular -ui-bootstrap (есть версии для обоих Bootstrap 3 и 2): http://angular-ui.github.io/bootstrap/