30

我试图将一些有角度的 js 模板字符串放在一个元素中,并期待一个编译的输出。但这并没有发生。

HTML

<div ng-controller="testController">
    <div ng-bind-html-unsafe="fruitsView"></div>
</div>

控制器:

function filterController($scope){
    ...
    $scope.arr = ["APPLE", "BANANA"];
    $scope.fruitsView = '<div><p ng-repeat="each in arr">{{each}}</p></div>';
}

输出只是{{each}}.

那么我如何$scope.fruitsView在元素内插入一个有角度的 js 模板字符串(这里)?

我为此做了一个小提琴

4

1 回答 1

95

In this case, you don't want to just "insert HTML", but compile it. You can create DOM nodes using the $compile service.

var tpl = $compile( '<div><p ng-repeat="each in arr">{{each}}</p></div>' )( scope );

As you can see, $compile returns a function that takes a scope object as a parameter, against which the code is evaluated. The resultant content can be inserted into the DOM with element.append(), for example.

Important note: But under no circumstances does any DOM-related code belong in your controller. The proper place is always a directive. This code can easily be thrown into a directive, but I wonder why you are programmatically inserting the HTML at all.

Can you shed some light here so I can provide a more specific answer?

Update

Assuming your data comes from a service:

.factory( 'myDataService', function () {
  return function () {
    // obviously would be $http
    return [ "Apple", "Banana", "Orange" ];
  };
});

And your template comes from a service

.factory( 'myTplService', function () {
  return function () {
    // obviously would be $http
    return '<div><p ng-repeat="item in items">{{item}}</p></div>';
  };
});

Then you create a simple directive that reads in the provided template, compiles it, and adds it to the display:

.directive( 'showData', function ( $compile ) {
  return {
    scope: true,
    link: function ( scope, element, attrs ) {
      var el;

      attrs.$observe( 'template', function ( tpl ) {
        if ( angular.isDefined( tpl ) ) {
          // compile the provided template against the current scope
          el = $compile( tpl )( scope );

          // stupid way of emptying the element
          element.html("");

          // add the template content
          element.append( el );
        }
      });
    }
  };
});

Then from your view:

<div ng-controller="MyCtrl">
   <button ng-click="showContent()">Show the Content</button>
   <div show-data template="{{template}}"></div>
</div>

And in the controller, you simply tie it together:

.controller( 'MyCtrl', function ( $scope, myDataService, myTplService ) {
  $scope.showContent = function () {
    $scope.items = myDataService(); // <- should be communicated to directive better
    $scope.template = myTplService();
  };
});

And it should all work together!

PS: this is all assuming your template comes from the server. If it doesn't, then your template should be in the directive, which simplifies things.

于 2013-02-13T05:29:31.543 回答