2016-05-02 13 views
1

Ich habe ein Array mit mehreren Objekten, die ähnlich wie diese:ng-repeat mit ng-bind-html als Pre- und Post-Markup

[ 
    { title: 'abc', 'pre': '<div class="class1"><div class="class2">', 'post': '</div>' }, 
    { title: 'def', 'pre': <div class="class3">', 'post': '</div>' }, 
    { title: 'ghi', 'pre': '<div class="class3">', 'post': '</div></div>' } 
] 

<div ng-repeat="item in myVar"> 
    <div ng-bind-html="item.pre" />{{ item.title }}<div ng-bind-html="item.post" /> 
</div> 

Die oben nicht funktioniert (ich zwei divs zu öffnen haben in Eins und schließen zwei andere Elemente in diesem Array, wie oben dargestellt). Das Problem ist, dass ng-bind-html an ein Element gebunden werden muss, die ich nicht verwenden kann, ebenso wenig wie eine Filter Arbeit:

<div ng-repeat="item in myVar"> 
    {{ item.pre | trust }}{{ item.title }}{{ item.post | trust }} 
</div> 

angular.module('myModule').filter('trust', ['$sce',function($sce) { 
    return function(value, type) { return $sce.trustAsHtml; } 
}]); 

Irgendwelche Ideen?

Antwort

1

Sie müssen die Verkettungsvorschau durchführen, vertrauen Sie darauf (oder aktivieren Sie ngSanitize, möglicherweise noch besser), dann injizieren Sie es.

Soweit ich weiß, gibt es keine Möglichkeit, ein partielles HTML-Element so zu injizieren, wie Sie es versuchen.

In Ihrem Controller:

$scope.items = [...]; 

for (var i = 0; i < $scope.items.length; i++) { 
    var e = $scope.items[i]; 

    e.concatenated = $sce.trustAsHtml(e.pre + e.title + e.post); 
} 

Dann Ihrer Ansicht:

<div ng-repeat="item in items"> 
    <div ng-bind-html="item.concatenated" /> 
</div> 

Natürlich, werden Sie wahrscheinlich wollen ngSanitize eingeschaltet, nur mit e.title alle Probleme zu vermeiden. Das heißt, wenn jemand einen Titel von <script>alert('ahh!')</script> eingeben würde, würde das am Ende vertrauenswürdig sein.


Ihre Version funktioniert nicht, weil, wie ngBindHtml geschrieben:

var ngBindHtmlDirective = ['$sce', '$parse', '$compile', function($sce, $parse, $compile) { 
    return { 
    restrict: 'A', 
    compile: function ngBindHtmlCompile(tElement, tAttrs) { 
     var ngBindHtmlGetter = $parse(tAttrs.ngBindHtml); 
     var ngBindHtmlWatch = $parse(tAttrs.ngBindHtml, function getStringValue(value) { 
     return (value || '').toString(); 
     }); 
     $compile.$$addBindingClass(tElement); 

     return function ngBindHtmlLink(scope, element, attr) { 
     $compile.$$addBindingInfo(element, attr.ngBindHtml); 

     scope.$watch(ngBindHtmlWatch, function ngBindHtmlWatchAction() { 
      // we re-evaluate the expr because we want a TrustedValueHolderType 
      // for $sce, not a string 
      element.html($sce.getTrustedHtml(ngBindHtmlGetter(scope)) || ''); 
     }); 
     }; 
    } 
    }; 
}]; 

Es injiziert element.html(...) verwenden, die ein vollständiges HTML-Element benötigt.

+0

Ich benutze ng-Sanitize, ja. Ist die Verbindung wirklich der einzige Weg? – chrney

+0

@chrney Ja, soweit ich weiß. Sehen Sie meine Bearbeitung für ein kleines bisschen warum. Es könnte eine Umgehungslösung sein, aber ehrlich gesagt wäre ich versucht, bei der Verkettung zu bleiben. Sie könnten eine Anweisung schreiben, um diese Verkettung durchzuführen, wenn es nötig ist. –