web-dev-qa-db-fra.com

Comment créer une directive d'info-bulle AngularJS avec un modèle compilé?

J'ai longuement et durement cherché sur Internet et je n'ai trouvé aucune réponse directe. Ma question est simple, je veux avoir quelque chose comme ça dans mon balisage:

<div my-tooltip-template="'mytt.tpl.html'" my-tooltip-scope="myDataItem">Some text...</div>

EDIT: myDataItem est une variable de portée qui contient mon objet de données, avec un modèle pouvant ressembler à:

<h1>{{dataItem.title}}</h1>
<span>{{dataItem.description}}</span>

Et je veux que ce modèle soit compilé avec la portée qui contient myDataItem en tant que dataItem et affichée sous forme d’info-bulle. Autant que je sache en expérimentant avec le module ui-bootstraptooltip, le moyen d'injecter du code HTML dans une info-bulle est d'utiliser la directive tooltip-html-unsafe mais le code HTML injecté n'est pas compilé. En d'autres termes, les expressions angulaires ne sont pas évaluées et les directives ne sont pas développées. etc.

Comment puis-je créer une directive pour cela? Je veux un résultat maigre, je ne veux pas avoir à inclure jQuery ou toute autre bibliothèque, juste AngularJS et ui-bootstrap.

Merci beaucoup!

7
Aviad P.

Voici les plans de la création d'une info-bulle en fonction de vos besoins (ou modifiez-la/intégrez-la avec l'info-bulle de ui-bootstrap).

app.directive("myTooltipTemplate", function($compile){
  var contentContainer;
  return {
    restrict: "A",
    scope: {
      myTooltipScope: "="
    },
    link: function(scope, element, attrs, ctrl, linker){
      var templateUrl = attrs.myTooltipTemplate;

      element.append("<div ng-include='\"" + templateUrl + "\"'></div>");
      var toolTipScope = scope.$new(true);
      angular.extend(toolTipScope, scope.myTooltipScope);
      $compile(element.contents())(toolTipScope);
    }
  };

});

Bien entendu, cela n’a aucune des fonctionnalités d’infos, telles que les popups, les placements, etc. - il ajoute simplement le modèle compilé à l’élément concerné par cette directive.

Plunker

Changement plunker avec un comportement plus proche de l'info-bulle;

6
New Dev

J'ai pu copier et remplacer la directive pour tooltip-html-unsafe

angular.module( 'ui.bootstrap.tooltip')
.directive( 'tooltipSpecialPopup', function () {
    return {
     restrict: 'EA',
     replace: true,
     scope: { content: '@', placement: '@', animation: '&', isOpen: '&' },
     templateUrl: 'tooltip.tpl.html'
  };
})

.directive( 'tooltipSpecial', [ '$tooltip', function ( $tooltip ) {
     return $tooltip( 'tooltipSpecial', 'tooltip', 'mouseenter' );
 }]);

Je viens de changer le bit peu sûr en spécial dans le nom de la directive et de changer le modèle.

Voici un Plunker

7
Dylan

J'ai trouvé cette question à la recherche d'une implémentation classique d'une info-bulle dans AngularJS, jQuery (et d'autres bibliothèques) gratuitement.

J'ai construit la directive suivante si quelqu'un en cherche une:

app.directive('tooltip', function($sce, $compile) {
    return {
        restrict: 'A',
        scope: {
            content: '=tooltipContent'
        },
        link: function(scope, element, attributes) {

            /* Attributes */

            scope.displayTooltip = false;

            /* Methods */

            scope.updateTooltipPosition = function(top, left) {
                tooltip.css({
                    top: top + 'px',
                    left: left + 'px',
                });
            };

            scope.getSafeContent = function(content) {
                return $sce.trustAsHtml(content);
            };

            /* Bootstrap */

            var tooltip = angular.element(
                '<div ng-show="displayTooltip" class="tooltip">\
                    <span ng-bind-html="getSafeContent(content)"></span>\
                </div>'
            );

            angular.element(document.querySelector('body')).append(tooltip);

            /* Bindings */

            element.on('mouseenter', function(event) {
                scope.displayTooltip = true;
                scope.$digest();
            });

            element.on('mousemove', function(event) {
                scope.updateTooltipPosition(event.clientY + 15, event.clientX + 15);
            });

            element.on('mouseleave', function() {
                scope.displayTooltip = false;
                scope.$digest();
            });

            /* Compile */

            $compile(tooltip)(scope);
        }
    };
});

Vous pouvez le tester ici: http://jsfiddle.net/m4sr9jmn/2/

J'espère que ça va aider!

2
Félix Veysseyre