AngularJS指令用于解析和替换自定义元素内容

时间:2014-01-06 14:36:01

标签: angularjs angularjs-directive

我想创建一个简单的markdown指令,它接受元素中的一些内容,解析它并用html替换它。

所以:

<markdown>#Heading</markdown>

或者,其中$ scope.heading ='#Heading';

<markdown>{{heading}}</markdown>

成为这样:

<h1>Heading</h1>

到目前为止我的指示(显然不完整!):

.directive('markdown', function () {
    return {
        restrict: 'E',
        replace: true,
        link: function ($scope, $element, $attrs) {
            // Grab contents
                var contents = /* How do I do this? */

                var newContents = Markdowner.transform(contents);

                // Replace <markdown> element with newContents
                /* How do I do this? */
        }
    }
})

我不确定如何获取指令的内容?我需要编译吗?!

解析Markdown只是一个例子

4 个答案:

答案 0 :(得分:7)

你走了!

Working Demo

app.directive('markdown', function() {
  return {
    restrict: 'E',
    transclude: true,
    compile: function(elem) {
      elem.replaceWith(Markdowner.transform(elem.html()));
    }
  }
});

答案 1 :(得分:6)

ngTransclude是专门为此设计的。

myModule.directive('heading', function() {
    return {
        restrict: 'E',
        replace: true,
        transclude: true,
        scope: true,
        template: '<h1 ng-transclude></h1>'
    };
}

然后像这样使用它:

<heading><span>{{foo}}</span></heading>

这是一个有效的fiddle(角度1.2.7)。

另外,我猜你需要某种降价整合。 Here's使用转码的版本,以便您最终获得div容器。

This one跳过整个转码行为,我猜它更接近你所追求的目标。

答案 2 :(得分:3)

您可以使用以下方法获取和设置链接函数中元素的已编译内容:

element.html() //get
element.html("blah") //set

以下是基于以下Sergiu示例的示例,该示例在调用降价转换器之前使用scope.$eval()处理html中包含的绑定:

http://jsfiddle.net/edeustace/4rE85/1/

angular.module('transclude', [])
 .directive('markdown', function() {

  var regex = /\{\{(.*?)\}\}/;

  var converter = new Showdown.converter();

  return {
    restrict: 'E',
    replace: true,
    scope: true,
    link: function (scope, element) {

      var processTemplate = function(text){
        var results = text.match(regex);
        if(!results){
          return text;
        } else {
          var value = scope.$eval(results[1]);
          var replaceKey = new RegExp("{{" + results[1] + "}}","g");
            text = text.replace(replaceKey, value);
            return processTemplate(text);
        }
     };
     var text = element.text();
     var processed = processTemplate(text);
     var markdownText = converter.makeHtml(processed);
     element.html(markdownText);
    }

  };
});

适用于:

<markdown>
# Bar {{foo}} {{foo}}
# {{bing}}
</markdown>

或者您可以将其绑定到您可以在指令中使用的属性:

app.directive('markdownWithBinding', function () {

  var converter = new Showdown.converter();

  return {
    restrict: 'E',
    scope: {
      'md' : '@'
    },
    link: function  ($scope, $element, $attrs) {

      $scope.$watch('md', function(newMd){

        var markdownText = converter.makeHtml(newMd);
        element.html(markdownText);

      });
    }
  }
});

像这样使用:

<markdown-with-binding md="Hello {{name}}"></markdown-with-binding> 
<!-- outputs Hello World!!! -->

旧答案

这将发生在link()中,用于将范围链接到元素。对于不需要范围的结构更改,最好在编译函数中进行更改:

app.directive('markdown', function () {

var link = function ($scope, $element, $attrs) {};
return {
    restrict: 'E',
    replace: true,
  compile: function($element, $attrs, $transclude){

    if($element.html() == "#Hello"){
      $element.html("<h1>Hello</h1>");
    }
    return link;
  },
}

});

以下是有关组件的精彩教程:http://www.youtube.com/watch?v=A6wq16Ow5Ec

答案 3 :(得分:0)

在您的链接功能上,AngularJS已经解析了您的HTML并用您的模板替换了内容(在您的情况下,由于您已将“replace”设置为true),因此将其丢失。

你可以从$元素中获取内部html内容,这是一个jQuery(jQLite)元素。

var contents = $element.innerHTML;