在控制器范围内调用函数的Angular指令

时间:2017-05-25 21:36:38

标签: javascript angularjs

我有一个Angular指令,用于搜索用户提交的文本并用锚标记替换网址。

function findUrls($compile) {
  var linkPatterns = new Array({
    pattern: /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig,
    template: '&nbsp;<a class="absolute_link" href="$1" target="_blank">$1</a>'
  },
  {
    pattern: /(^|[^\/])(www\.[\S]+(\b|$))/ig,
    template: '&nbsp;<a class="absolute_link" href="http://$2" ng-click="alert(\'hello\')" target="_blank">$2</a>'
  },
  {
    pattern: /([a-z0-9._-]+@[a-z0-9._-]+\.[a-zA-Z0-9._-]+)/ig,
    template: '&nbsp;<a class="absolute_link" href="mailto:$1" ng-click="alert(\'hello\')" target="_blank">$1</a>'
  },
  {
    pattern: /(^|[^a-z0-9@\\\/._-])([a-z0-9]{0,256}\.(com|net|org|edu)([a-z0-9\/?=\-_#]{0,256})?(\b|$))/ig,
    template: '&nbsp;<a class="absolute_link" href="http://$2" ng-click="alert(\'hello\')" target="_blank">$2</a>'
  });

  return {
    restrict: 'AC',
    link: function (scope, elem, attrs) {
      if (attrs.ngBind) {
        scope.$watch(attrs.ngBind, _.debounce(wrapUrls));
      }
      if (attrs.ngBindHtml) {
        scope.$watch(attrs.ngBindHtml, _.debounce(wrapUrls));
      }

      function wrapUrls(text) {
        var html = elem.html();
        var newHtml = html;

        linkPatterns.forEach((item) => {
          newHtml = newHtml.replace(item.pattern, item.template);
        });

        if (html !== newHtml) {
          elem.html(newHtml);
          $compile(elem.contents())(scope);
        }
      }
    }
  };
}

当用户点击其中一个链接时,我希望能够捕获该点击并记录有关其所属对象的一些信息。但是,该指令不知道它们属于哪个对象,因此应该在控制器上处理记录点击的代码。

我希望指令通知控制器已单击其中一个元素,控制器将记录对象的属性,但我不知道从哪里开始。

1 个答案:

答案 0 :(得分:3)

您可以将控制器功能传递给指令,并在单击链接时从指令调用它

return {
    restrict: 'AC',
    scope: {               // **** Add this *****
        alert: '&'   
    }
    link: function (scope, elem, attrs) {
    if (attrs.ngBind) {
        scope.$watch(attrs.ngBind, _.debounce(wrapUrls));
    }
    if (attrs.ngBindHtml) {
        scope.$watch(attrs.ngBindHtml, _.debounce(wrapUrls));
    }

    function wrapUrls(text) {
        var html = elem.html();
        var newHtml = html;

        linkPatterns.forEach((item) => {
           newHtml = newHtml.replace(item.pattern, item.template);
        });

        if (html !== newHtml) {
            elem.html(newHtml);
            $compile(elem.contents())(scope);
        }
    }
}

<div DIRECTIVE_NAME alert="notify(msg)"></div> //controllers notify function