Angularjs指令替换文本

时间:2013-02-04 18:01:25

标签: javascript angularjs

我如何在angularjs中创建一个指令,例如接受这个元素:

<div>Example text http://example.com</div>

并将其转换为此

<div>Example text <a href="http://example.com">http://example.com</a></div>

我已经编写了自动链接函数中文本的函数并返回html(让我们调用函数“autoLink”)但是我的指令并没有达到标准。

我还想在元素中添加一个属性,将对象传递给指令。 e.g。

<div linkprops="link.props" >Example text http://example.com</div>

其中link.props是像{a:'bla bla',b:'waa waa'}这样的对象,它将作为第二个参数传递给autoLink函数(第一个是文本)。

6 个答案:

答案 0 :(得分:38)

两种方式:

指令

app.directive('parseUrl', function () {
    var urlPattern = /(http|ftp|https):\/\/[\w-]+(\.[\w-]+)+([\w.,@?^=%&amp;:\/~+#-]*[\w@?^=%&amp;\/~+#-])?/gi;
    return {
        restrict: 'A',
        require: 'ngModel',
        replace: true,
        scope: {
            props: '=parseUrl',
            ngModel: '=ngModel'
        },
        link: function compile(scope, element, attrs, controller) {
            scope.$watch('ngModel', function (value) {
                var html = value.replace(urlPattern, '<a target="' + scope.props.target + '" href="$&">$&</a>') + " | " + scope.props.otherProp;
                element.html(html);
            });
        }
    };
});

HTML:

<p parse-url="props" ng-model="text"></p>

过滤

app.filter('parseUrlFilter', function () {
    var urlPattern = /(http|ftp|https):\/\/[\w-]+(\.[\w-]+)+([\w.,@?^=%&amp;:\/~+#-]*[\w@?^=%&amp;\/~+#-])?/gi;
    return function (text, target, otherProp) {
        return text.replace(urlPattern, '<a target="' + target + '" href="$&">$&</a>') + " | " + otherProp;
    };
});

HTML:

<p ng-bind-html-unsafe="text | parseUrlFilter:'_blank':'otherProperty'"></p>

注意:'otherProperty'仅作为示例,以防您想要将更多属性传递到过滤器中。

<强> jsFiddle

更新:改进了替换算法。

答案 1 :(得分:5)

要回答这个问题的前半部分,没有额外的属性要求,可以使用Angular的linky过滤器:https://docs.angularjs.org/api/ngSanitize/filter/linky

答案 2 :(得分:4)

如果有多个链接,则最高投票的答案无效。 Linky已经为我们完成了90%的工作,唯一的问题是它清理了html,从而删除了html / newlines。我的解决方案是只编辑linky过滤器(下面是Angular 1.2.19)以不清理输入。

app.filter('linkyUnsanitized', ['$sanitize', function($sanitize) {
  var LINKY_URL_REGEXP =
        /((ftp|https?):\/\/|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>]/,
      MAILTO_REGEXP = /^mailto:/;

  return function(text, target) {
    if (!text) return text;
    var match;
    var raw = text;
    var html = [];
    var url;
    var i;
    while ((match = raw.match(LINKY_URL_REGEXP))) {
      // We can not end in these as they are sometimes found at the end of the sentence
      url = match[0];
      // if we did not match ftp/http/mailto then assume mailto
      if (match[2] == match[3]) url = 'mailto:' + url;
      i = match.index;
      addText(raw.substr(0, i));
      addLink(url, match[0].replace(MAILTO_REGEXP, ''));
      raw = raw.substring(i + match[0].length);
    }
    addText(raw);
    return html.join('');

    function addText(text) {
      if (!text) {
        return;
      }
      html.push(text);
    }

    function addLink(url, text) {
      html.push('<a ');
      if (angular.isDefined(target)) {
        html.push('target="');
        html.push(target);
        html.push('" ');
      }
      html.push('href="');
      html.push(url);
      html.push('">');
      addText(text);
      html.push('</a>');
    }
  };
}]);

答案 3 :(得分:1)

我想要一个交换文字的暂停按钮。我是这样做的:

CSS中的

.playpause.paused .pause, .playpause .play { display:none; }
.playpause.paused .play { display:inline; }
模板中的

<button class="playpause" ng-class="{paused:paused}" ng-click="paused = !paused">
  <span class="play">play</span><span class="pause">pause</span>
</button>

答案 4 :(得分:0)

我会在指令的链接函数中分析文本:

directive("myDirective", function(){

  return {
        restrict: "A",
        link: function(scope, element, attrs){
          // use the 'element' to manipulate it's contents...
        }
      }
  });

答案 5 :(得分:0)

受到@Neal的启发,我从新的Angular 1.5.8中做了这个“no sanitize”过滤器。它还识别没有ftp | http(s)的地址,但是以www开头。这意味着RedirectMatch 301 ^/(media-center)/\d+-(.+)$ /$1/$2 https://google.com都将被链接。

www.google.com