/ 筆記

[天真] Angular + $compile + ng-bind-html 你看看你

自從我膝蓋中了一箭,AngularJS 什麼的就全部都忘光光惹!本來還天真的以為 ng- 天下無敵,結果本來想偷懶直接 ng-bind-html 然後惡搞一下,結果就 GG 惹!


具體的需求與作法大概是,

  • content 是由使用者產生的 HTML 內容,無法有統一的樣版。
  • $alert() 透過特殊的 Service 來呼叫一個燈箱,燈箱中顯示 content 內容。
  • ng-bind-html 雖然可以透過 $sce 來產出,不過餵給他基本上沒什麼效果。
  • $compile 可以用他來重做一次 HTML 內容,最後在餵給 content 讓他輸出,但是,同樣不能綁在 ng-bind-html 底下,不然 $compile 等於做白工。
  • directive 最後自訂一個 Directive 來讓 content 可以正常出現在畫面上,並且吃到我們想要餵給他的 $scope

所以如果有個 content 長成這樣,


$scope.sayHello = function(string) {
  $log.info(string);
};

var content = '<a ng-click="sayHello(\'Hello\')">Say Hello</a>';

如果本來的 Service 是這樣,

$alert({
  scope: $scope,
  content: content
});

然後這個 Service 使用的 Template 是這樣,

<div class="alert-message">
  <div ng-bind-html="content"></div>
</div>

所以,本來我想偷懶直接給 content 偷塞 $scope 進去,結果不成。用 $compile 或是 $sce 做過再去餵給 ng-bind-html 一樣死掉。所以,基本上就是只能用 Directive + $compile 來解決。

所以,改一下 Template,

<div class="alert-message">
  <div show-content template="{{ content }}"></div>
</div>

偷偷做一個 Directive 來做 content 的內容,

.directive('showContent', ['$compile', function ($compile) {
  return {
    scope: true,
    link: function($scope, $element, $attr) {
      var el;
      $attrs.$observe('template', function (tpl) {
        el = $compile('<div>'+tpl+'</div>')($scope);
        $element.html("");
        $element.append(el);
      });
    }
  };
}]);

參考:Insert an angular js template string inside an element