20

たとえば、この要素を取得するディレクティブをangularjsで作成するにはどうすればよいですか?

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

そしてそれをこれに変換します

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

関数内のテキストを自動リンクしてhtmlを返す機能(関数を「autoLink」と呼びましょう)はすでに作成されていますが、ディレクティブをスクラッチすることはできません。

また、オブジェクトをディレクティブに渡すために、要素に属性を追加したいと思います。例えば

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

link.propsは、{a:'bla bla'、b:'waa waa'}のようなオブジェクトであり、2番目のパラメーター(最初はテキスト)としてautoLink関数に渡されます。

4

6 に答える 6

40

それを行う2つの方法:

指令

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

更新:置換アルゴリズムが改善されました。

于 2013-02-04T18:43:57.233 に答える
6

この質問の前半に答えるには、追加のプロパティ要件なしで、Angularのlinkyフィルターを使用できます:https ://docs.angularjs.org/api/ngSanitize/filter/linky

于 2014-05-07T19:16:35.287 に答える
5

複数のリンクがある場合、上位投票の回答は機能しません。Linkyはすでに90%の作業を行っていますが、唯一の問題は、htmlをサニタイズしてhtml/newlinesを削除することです。私の解決策は、入力をサニタイズしないように、リンキーフィルター(以下は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>');
    }
  };
}]);
于 2014-06-18T17:02:10.863 に答える
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>
于 2014-02-21T12:31:21.413 に答える
1

@Nealに触発されて、新しいAngular1.5.8からこの「サニタイズなし」フィルターを作成しました。また、ftp | http(s)がなく、wwwで始まるアドレスも認識します。これは、との両方がリンクされることを意味しhttps://google.comますwww.google.com

angular.module('filter.parselinks',[])

.filter('parseLinks', ParseLinks);

function ParseLinks() {
  var LINKY_URL_REGEXP =
        /((ftp|https?):\/\/|(www\.)|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>"\u201d\u2019]/i,
      MAILTO_REGEXP = /^mailto:/i;

  var isDefined = angular.isDefined;
  var isFunction = angular.isFunction;
  var isObject = angular.isObject;
  var isString = angular.isString;

  return function(text, target, attributes) {
    if (text == null || text === '') return text;
    if (typeof text !== 'string') return text;

    var attributesFn =
      isFunction(attributes) ? attributes :
      isObject(attributes) ? function getAttributesObject() {return attributes;} :
      function getEmptyAttributesObject() {return {};};

    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/www/mailto then assume mailto
      if (!match[2] && !match[4]) {
        url = (match[3] ? 'http://' : '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) {
      var key, linkAttributes = attributesFn(url);
      html.push('<a ');

      for (key in linkAttributes) {
        html.push(key + '="' + linkAttributes[key] + '" ');
      }

      if (isDefined(target) && !('target' in linkAttributes)) {
        html.push('target="',
                  target,
                  '" ');
      }
      html.push('href="',
                url.replace(/"/g, '&quot;'),
                '">');
      addText(text);
      html.push('</a>');
    }
  };
}
于 2017-12-15T20:01:43.990 に答える
0

ディレクティブのリンク関数のテキストを分析します。

directive("myDirective", function(){

  return {
        restrict: "A",
        link: function(scope, element, attrs){
          // use the 'element' to manipulate it's contents...
        }
      }
  });
于 2013-02-04T18:06:29.553 に答える