web-dev-qa-db-fra.com

Comment faire pour que ng-bind-html compile du code angularjs

Je travaille avec angularjs 1.2.0-rc.3. Je voudrais inclure dynamiquement du code html dans un modèle. Pour cela j'utilise dans le contrôleur:

html = "<div>hello</div>";
$scope.unicTabContent = $sce.trustAsHtml(html);

Dans le modèle, j'ai obtenu:

<div id="unicTab" ng-bind-html="unicTabContent"></div>

Cela fonctionne très bien pour le code html normal. Mais quand j'essaye de mettre angular il n'est pas interprété, il est juste inclus dans la page. Par exemple, j'aimerais inclure:

<div ng-controller="formCtrl">
    <div ng-repeat="item in content" ng-init="init()">
    </div>
</div>

Merci beaucoup

52
Clement Roblot

Cette solution n'utilise pas de modèles codés en dur, et vous pouvez compiler Angular incorporées dans une réponse API.


Étape 1. Installez cette directive: https://github.com/incuna/angular-bind-html-compile

Étape 2. Incluez la directive dans le module.

angular.module("app", ["angular-bind-html-compile"])

Étape 3. Utilisez la directive dans le modèle:

<div bind-html-compile="letterTemplate.content"></div>

Résultat:

Objet contrôleur

 $scope.letter = { user: { name: "John"}}

Réponse de JSON

{ "letterTemplate":[
    { content: "<span>Dear {{letter.user.name}},</span>" }
]}

Sortie HTML =

<div bind-html-compile="letterTemplate.content"> 
   <span>Dear John,</span>
</div>

Pour référence, voici la directive pertinente:

(function () {
    'use strict';

    var module = angular.module('angular-bind-html-compile', []);

    module.directive('bindHtmlCompile', ['$compile', function ($compile) {
        return {
            restrict: 'A',
            link: function (scope, element, attrs) {
                scope.$watch(function () {
                    return scope.$eval(attrs.bindHtmlCompile);
                }, function (value) {
                    element.html(value);
                    $compile(element.contents())(scope);
                });
            }
        };
    }]);
}());
77
Ryan.lay

C'est ce que j'ai fait, aucune idée si c'est la angularTM, mais cela fonctionne et est super simple;

.directive('dynamic', function($compile) {
    return {
        restrict: 'A',
        replace: true,
        link: function (scope, element, attrs) {
            scope.$watch(attrs.dynamic, function(html) {
                $compile(element.html(html).contents())(scope);
            });
        }
    };
});

Alors;

<div id="unicTab" dynamic="unicTabContent"></div>

Edit: J'ai trouvé le angular , et c'est super simple.

$templateCache.put('unicTabContent', $sce.trustAsHtml(html));
<div id="unicTab" ng-include="'unicTabContent'"></div>

Pas besoin de faire vos propres directives ou quoi que ce soit. Mais c'est une sorte d'accord unique, il ne verra pas les modifications apportées à votre html comme la directive personnalisée le fait .

19
Hashbrown

J'essayais de faire la même chose et suis tombé sur ce module.

http://ngmodules.org/modules/ng-html-compile

Je viens de l'inclure et j'ai pu utiliser "ng-html-compile" au lieu de "ng-bind-html"

2
nbarth

Comme le dit Vinod Louis dans son commentaire, la meilleure façon de le faire était d'utiliser des modèles. J'ai dû définir un modèle en dehors du code normal, par exemple j'ai ajouté ce code à l'intérieur de mon index.html:

<script type="text/ng-template" id="unic_tab_template.html">
    <div ng-switch on="page">
        <div ng-switch-when="home"><p>{{home}}</p></div>
        <div ng-switch-when="form">
            <div ng-controller="formCtrl">
                <div ng-repeat="item in content">{{item.name}}:{{item.value}}</div>
            </div>
        </div>
        <div ng-switch-default>an error accured</div>
    </div>
</script>

Ce modèle est conditionnel, donc en fonction de la valeur de $ scope.page, il bascule entre les 3 modèles (le troisième étant un gestionnaire d'erreurs). Pour l'utiliser, j'avais:

<div id="unicTab" ng-controller="unicTabCtrl">
    <div ng-include="'unic_tab_template.html'"></div>
</div>

De cette façon, ma page change en fonction de la portée $ à l'intérieur de mon contrôleur unicTabCtrl.

Pour conclure, l'idée d'insérer des joints de gabarit angularsjs est difficile à réaliser ($ compile les coutures pour être la solution, mais je n'ai pas pu le faire fonctionner). Mais à la place, vous pouvez utiliser des modèles conditionnels.

2
Clement Roblot

Ma solution à un problème similaire dans mon application actuelle sans utiliser de modèle (pas élégant, mais qui fonctionne):

directive('ngBindHtmlCompile', ['$compile', function ($compile) {
    return {
        restrict: 'A',
        compile: function compile(tElement, tAttributes, transcludeFn) {
            return function postLink(scope, element, attributes) {
                scope.$watch(function() {
                    return scope.$eval(attributes.ngBindHtml);
                }, function(newValue, oldValue) {
                    $compile(element.children())(scope);
                });
            };
        }
    };
}]);

Il requiert ngBindHtml sur le même élément et compile le contenu de l'élément après qu'il change avec ngBindHtml.

<div id="unicTab" ng-bind-html="unicTabContent" ng-bind-html-compile></div>

ng-html-compile est similaire mais à première vue, il ne sera pas recalculé lorsque le contenu du modèle change. Mais je ne l'ai pas essayé.

1
Lukasz Frankowski

Une façon consiste à utiliser une directive dans le but d'insérer des modèles personnalisés qui incluent angular

<div id="unicTab" unic-tab-content></div>
app.directive("unicTabContent",function(){
   return {
      restrict:"A",
      template:'{{unicTabContent}}'
   }
})
1
charlietfl

Une solution beaucoup plus simplifiée de @ clement-roblot basée sur des modèles intégrés.

Manette:

app.controller('TestCtrl', [
    '$scope',
    '$templateCache',
    function ($scope, $templateCache) {
        $templateCache.put('test.html', '2 + 2 = {{ 2 + 2 }}');
    }
]);

Vue:

<div ng-include="'test.html'"></div>
0
Stalinko

Le code ci-dessous est beaucoup plus simple en utilisant les objets $ interpolate et $ sce intégrés d'Angular. Injectez d'abord les objets $ interpolate et $ sce Angular dans votre directive car vous faites tout ce dont vous avez besoin dans votre directive.

amqApp.directive('myDir', ['$interpolate', '$sce', function ($interpolate,$sce ) {...}

Créez ensuite toutes vos variables de portée trouvées dans vos expressions html importées ...

$scope.custom = 'Hello World';

Ensuite, utilisez $ interpolate pour traiter votre code HTML personnalisé et ses expressions ... puis assurez-vous d'utiliser l'objet $ sce pour lui faire confiance en HTML avant de le lier ...

var html = $interpolate('<b>{{custom}}</b>')($scope);    
$scope.data = $sce.trustAsHtml(html);

Enfin, dans votre vue, assurez-vous simplement d'utiliser un élément avec "ng-bind" ou "ng-bind-html" dessus dans votre affichage de vue. J'ai trouvé que la pièce $ sce n'affiche pas le HTML en HTML (le voit comme du texte) si vous ne le liez pas dans votre modèle html comme ceci ...

<span ng-bind-html="data"></span>

Vous devriez voir en gras ...

Bonjour tout le monde

J'ai utilisé cette astuce pour importer du texte/HTML avec un angular {{expressions}} personnalisé à partir d'un web.config.

0
Stokely