web-dev-qa-db-fra.com

Comment créer une interface utilisateur AngularJS bootstrap popover avec du contenu HTML?)

Je veux créer un bootstrap popover avec une balise pré contenant un objet JSON prétexté. La mise en œuvre naïve,

<span popover='<pre>{[ some_obj | json:"  " ]}</pre>'
      popover-trigger='mouseenter'>

échappe au contenu avant de l'insérer dans la fenêtre contextuelle. Quelle est la meilleure façon de spécifier un corps popover avec un contenu HTML?

43
Andrey Fedorov

[~ # ~] met à jour [~ # ~] :

Comme on peut le voir dans this , vous devriez maintenant pouvoir le faire sans remplacer le modèle par défaut.

ORIGINAL:

À partir de angular 1.2+ ng-bind-html-unsafe a été retiré. vous devriez utiliser le service $ sce . référence .

Voici un filtre pour créer du code HTML de confiance.

MyApp.filter('unsafe', ['$sce', function ($sce) {
    return function (val) {
        return $sce.trustAsHtml(val);
    };
}]);

Voici le modèle angulaire écrasé Bootstrap 0.11.2 utilisant ce filtre

// update popover template for binding unsafe html
angular.module("template/popover/popover.html", []).run(["$templateCache", function ($templateCache) {
    $templateCache.put("template/popover/popover.html",
      "<div class=\"popover {{placement}}\" ng-class=\"{ in: isOpen(), fade: animation() }\">\n" +
      "  <div class=\"arrow\"></div>\n" +
      "\n" +
      "  <div class=\"popover-inner\">\n" +
      "      <h3 class=\"popover-title\" ng-bind-html=\"title | unsafe\" ng-show=\"title\"></h3>\n" +
      "      <div class=\"popover-content\"ng-bind-html=\"content | unsafe\"></div>\n" +
      "  </div>\n" +
      "</div>\n" +
      "");
}]);

EDIT: Voici une implémentation de Plunker .

EDIT 2: Comme cette réponse ne cesse de recevoir des hits, je la garderai à jour du mieux que je peux. À titre de référence Ici est le modèle du repo angular-ui bootstrap). Si cela change, le modèle de remplacement nécessitera des mises à jour correspondantes et l'ajout du ng-bind-html=\"title | unsafe\" et ng-bind-html=\"content | unsafe\" attributs pour continuer à travailler.

Pour une conversation mise à jour, consultez le numéro ici .

71
Matthew.Lothian

Utilisez la directive popover-template

Si vous utilisez une version de angular-ui égale ou supérieure 0.13.0 , votre meilleure option est d'utiliser le popover-template directive. Voici comment l'utiliser:

<button popover-template="'popover.html'">My HTML popover</button>

<script type="text/ng-template" id="popover.html">
    <div>
        Popover content
    </div>
</script>

NB: N'oubliez pas les guillemets autour du nom du template dans popover-template="'popover.html'".

Voir démo plunker


En remarque, il est possible d'externaliser le modèle popover dans un fichier HTML dédié, au lieu de le déclarer dans un fichier <script type="text/ng-template> élément comme ci-dessus.

Voir deuxième démonstration

24
Michael P. Bazos

J'ai posté une solution sur le projet github: https://github.com/angular-ui/bootstrap/issues/52

Si vous souhaitez ajouter cette fonctionnalité à votre projet, voici un correctif.

Ajoutez ces directives:

angular.module("XXX")
    .directive("popoverHtmlUnsafePopup", function () {
      return {
        restrict: "EA",
        replace: true,
        scope: { title: "@", content: "@", placement: "@", animation: "&", isOpen: "&" },
        templateUrl: "template/popover/popover-html-unsafe-popup.html"
      };
    })

    .directive("popoverHtmlUnsafe", [ "$tooltip", function ($tooltip) {
      return $tooltip("popoverHtmlUnsafe", "popover", "click");
    }]);

Et ajoutez le modèle:

<div class="popover {{placement}}" ng-class="{ in: isOpen(), fade: animation() }">
  <div class="arrow"></div>

  <div class="popover-inner">
      <h3 class="popover-title" ng-bind="title" ng-show="title"></h3>
      <div class="popover-content" bind-html-unsafe="content"></div>
  </div>
</div>

Utilisation: <button popover-placement="top" popover-html-unsafe="On the <b>Top!</b>" class="btn btn-default">Top</button>

Voir sur plunkr: http://plnkr.co/edit/VhYAD04ETQsJ2dY3Uum3?p=preview

9
user1067920

Vous devez modifier le modèle popover par défaut pour spécifier que vous souhaitez autoriser le contenu HTML. Regarde le popover-content div, sa liaison avec la propriété content permet de créer du code HTML non sécurisé:

 angular.module("template/popover/popover.html", []).run(["$templateCache", function ($templateCache) {
        $templateCache.put("template/popover/popover.html",
            "<div class='popover {{placement}}' ng-class='{ in: isOpen(), fade: animation() }'>" + 
            "<div class='arrow'></div><div class='popover-inner'>" + 
            "<h3 class='popover-title' ng-bind='title' ng-show='title'></h3>" + 
            "<div class='popover-content' ng-bind-html-unsafe='content'></div>" +
            "<button class='btn btn-cancel' ng-click='manualHide()'>Cancel</button>" +
            "<button class='btn btn-apply' ng-click='manualHide()'>Apply</button></div></div>");
    }]);
6
Andres

Pour tous vos besoins classiques Bootstrap popover, vous pouvez utiliser la directive angular. Cette directive supprime tout enchevêtrement du modèle HTML et est très facile à utiliser. utilisation.

Vous pouvez configurer l'événement title, content de popover, placement, ouvrir/fermer en fondu delay, trigger et indiquer si le contenu doit être traité comme html. Il empêche également le débordement et l'écrêtage du contenu.

Liens connexes avec tous les codes ici http://plnkr.co/edit/MOqhJi

Capture d'écran

imgur

Utilisation

<!-- HTML -->
<div ng-model="popup.content" popup="popup.options">Some element</div>

/* JavaScript */
this.popup = {
  content: 'Popup content here',
  options: {
    title: null,
    placement: 'right', 
    delay: { show: 800, hide: 100 }
  }
}; 

JavaScript

/**
 * Popup, a Bootstrap popover wrapper.
 *
 * Usage: 
 *  <div ng-model="model" popup="options"></div>
 * 
 * Remarks: 
 *  To prevent content overflow and clipping, use CSS
 *  .popover { Word-wrap: break-Word; }
 *  Popup without title and content will not be shown.
 *
 * @param {String}  ngModel           popup content
 * @param {Object}  options           popup options
 * @param {String}  options.title     title
 * @param {Boolean} options.html      content should be treated as html markup
 * @param {String}  options.placement placement (top, bottom, left or right)
 * @param {String}  options.trigger   trigger event, default is hover
 * @param {Object}  options.delay     milliseconds or { show:<ms>, hide:<ms> }
 */
app.directive('popup', function() {
  return {
    restrict: 'A',
    require: 'ngModel',
    scope: {
      ngModel: '=',
      options: '=popup'
    },
    link: function(scope, element) {
      scope.$watch('ngModel', function(val) {
        element.attr('data-content', val);
      });

      var options = scope.options || {} ; 

      var title = options.title || null;
      var placement = options.placement || 'right';
      var html = options.html || false;
      var delay = options.delay ? angular.toJson(options.delay) : null;
      var trigger = options.trigger || 'hover';

      element.attr('title', title);
      element.attr('data-placement', placement);
      element.attr('data-html', html);
      element.attr('data-delay', delay);
      element.popover({ trigger: trigger });
    }
  };
});
6
Mikko Viitala

Voir https://github.com/jbruni/bootstrap-bower-jbruni , qui permet d'utiliser un template popover

3
Thierry

Le style CSS suivant semble avoir fait ce que je voulais dans mon cas spécifique:

.popover-content {
  white-space: pre;
  font-family: monospace;
}

La question générale reste encore ouverte.

1
Andrey Fedorov