Comment ajouter angularjs ui bootstrap tooltips dynamiquement au balisage existant?

Relativement nouveau pour angularjs. Aidez-moi à comprendre ce qui se passe ici!

Ce que je tente finalement d'accomplir: compte tenu d'un bloc de texte dans mon html (par exemple, dans un élément de paragraphe), je souhaite ajouter des info-bulles (bootstrap tooltips pour être exact) à des mots sélectionnés dans le texte. Donc, par exemple, si un utilisateur tape le monde "bonjour" dans un champ de recherche, toutes les instances de "bonjour" dans le paragraphe afficheront une info-bulle lorsque survoleront, affichant un message comme une définition ou quelque chose.

REMARQUE: Je ne pense pas avoir été clair sur cela initialement, mais le bloc de texte auquel je souhaite ajouter la info-bulle est déjà dans le html et n'aura aucun type de marquage d'étiquette de directive qui l'entoure. Voir mon violon pour une illustration.

Je l'ai fait dans jQuery … maintenant, j'essaie de le faire fonctionner dans angularjs!

Ma première tentative était d'utiliser un filtre personnalisé avec un regex qui insérera une balise "a" avec les attributs tooltip dans le paragraphe aux emplacements appropriés. Le nouveau balisage apparaît, mais ne semble pas être "vu" par angularjs (pas tout à fait sûr de la terminologie pour le moment mais je pense que ça ne s'entend pas "??).

Voici le problème sur l'illustration de jsfiddle:

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

(1) La première ligne de la sortie a une info-bulle fonctionnelle sur "foo" … elle a juste les attributs tooltip directement dans le balisage. Html généré:

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

(2) La deuxième ligne utilise ng-bind-html, et possède les attributs, mais pas une info-bulle. Html généré:

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

(3) La troisième ligne utilise le filtre et possède les attributs, mais pas une info-bulle. Html généré:

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

Ma question principale est … comment résoudre la tâche que j'ai décrite ci-dessus?

La question secondaire consiste à comprendre ce qui se passe dans chacun des 3 exemples ci-dessus. J'ai remarqué que la sortie directe dans (1) a une classe "ng-scope" insérée par angulaire dans le balisage généré. Les deux autres n'ont pas cela, mais ont une classe de liaison ng insérée dans la balise parent p. Je ne sais pas ce qui se passe ici, mais je pense qu'il a quelque chose à voir avec mon problème.

J'ai l'impression que la solution peut impliquer une directive, mais je ne suis pas sûr de la façon d'appliquer cette directive au texte existant (c.-à-d., Étiquette ap déjà dans le balisage).

Merci!

EDIT: a mis à jour le jsfiddle pour refléter plus précisément le problème (quatrième ligne dans la sortie)

La manière appropriée de gérer le HTML serait une directive angulaire, permet de créer une directive (par exemple, dynamic-tooltip ) prenant deux paramètres

  • Message d'outil
  • Votre mot de recherche

En HTML

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

The searchElement sera searchElement avec n'importe quel modèle comme

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

Ici, lorsque vous cliquez sur le bouton de search , la valeur que vous avez saisie dans le champ de recherche sera définie dans searchElement

La définition de la directive est:

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

La directive $watch tooltip-element , donc, lorsque vous modifiez la valeur, essayez d'en supprimer les info-bulles, puis essayez de faire correspondre votre search-word si vous en avez trouvé, puis créez la info-bulle.

Vérifiez la démo

MODIFIER:

Je pense que j'ai mal compris vos besoins. Surtout après avoir remarqué que vous utilisez déjà le module angulaire ui-boostrap.

Le problème ici, je pense, est que les nouveaux attributs que vous attachez ne sont pas compilés par Angular, donc la directive tooltip n'est jamais exécutée. Vous devez exécuter le HTML / DOM nouvellement joint par $ compile (element) (scope).

Exemple de directive. Veuillez noter que ce n'est pas complet, considérez-le comme un pseudocode que toute autre chose, mais cela devrait servir de guide pour la façon de le faire. Fondamentalement, vous pouvez utiliser n'importe quel jQuery que vous voulez dans la directive, il est important de noter que le 'elem' que vous obtenez dans la fonction de lien est le même élément auquel la directive est liée. De plus, vous devez appeler $ compile (votre_élément) (scope) sur n'importe quel HTML / DOM que vous créez et vous attachez.

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

C'est probablement une approche naïve, mais je ne connais pas pleinement vos besoins. Mais il devrait vous donner une idée d'un moyen possible de résoudre ce problème.


Je pense que vous approchez le problème de la mauvaise façon. Il existe une règle générale lors de l'utilisation angulaire, c'est-à-dire: si vous modifiez le DOM, vous (presque toujours) ont besoin d'une directive.

Alors, qu'est-ce qui ne va pas ici?

Je ne suis pas très familier avec l'implémentation d'info-bulle de Bootstrap, mais je suppose qu'il ne reprend jamais les attributs nouvellement ajoutés de «tooltip». Je crois que la raison pour laquelle il fonctionne dans le premier exemple est que le code relatif à l'info-bulle recherche le DOM pour les attributs d'info-bulle sur la charge de la page, mais l'ajout après cela est un non-aller (corrigez-moi si je me trompe).

Alors, comment pouvez-vous résoudre ce problème?

Je crois que vous voulez ajouter de manière dynamique des info-bulles d'une façon ou d'une autre? Je pense que angular-ui bootstrap possède déjà des directives qui le supportent, par exemple ui-tooltip="{{variable.on.scope}}" . Voir le lien plus bas.

Ou, si vous avez besoin d'autre chose, vous devez créer votre propre directive. Les directives peuvent être effrayantes au début, mais elles sont (à mon avis) la caractéristique la plus importante d'Angular et assez simple à utiliser une fois que vous en avez la trace.

Essentiellement, lors de la création d'une nouvelle directive, vous pouvez transmettre les données définissant le texte souhaité dans la info-bulle. À l'intérieur de la fonction de liaison (scope, elem, attrs) dans votre directive, vous pouvez attacher une info-bulle (à l'aide de la fonction elem.tooltip () de Bootstrap) à l'élément 'elem', étant l'élément auquel la directive s'applique.

Si vous devez également associer l'élément <a> , vous pouvez utiliser la transclusion, un peu plus avancée.

Si vous ne connaissez pas les directives, lisez la suite et demandez si vous avez besoin d'aide supplémentaire. Ou tout simplement vérifier angular-ui-bootstrap (il existe des versions pour Bootstrap 3 et 2): http://angular-ui.github.io/bootstrap/