简体   繁体   中英

Angular directive passing arguments to controller function within element's .html()

The following works and console dot logs the "post" object, but how do I pass the url of the anchor tag in the directive to the controller function "itemClicked"?

HTML:

<div ng-repeat="post in posts" >
    <div find-urls link-clicked="itemClicked(post)" ng-bind="post.content"><div>
</div>

Controller:

$scope.itemClicked = function(post) {
  console.log(post);
};

Directive:

function findUrls($compile) {
  return {
    restrict: 'AC',
    scope: {
        linkClickedCallback: '&linkClicked'
    },
    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 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="linkClickedCallback();" 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="linkClickedCallback();" 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="linkClickedCallback();" target="_blank">$2</a>'
        });

        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);
        }
      }
    }
  };
}

It's easy to implement with $scope.$emit and $scope.$on .

In your directive:

scope.$emit('passUrl', urlToPass);

In your controller:

$scope.$on('passUrl', function (event, data) {
  $log.debug(data); // received urlToPass variable from directive
})

It looks like what I was missing was how to pass the arguments into the linkClickedCallback function on the controller. You need to pass in arguments to the function through an object {arg1: 5, arg2: 10} and then add them to the function in the HTML in the same order to pass them along to the controller.

I have created the object {link: 1} to pass into linkedClickedCallback where 1 is a hard coded value. When the example runs it outputs 1 and on the following line the "post" object defined in the HTML.

HTML:

<div ng-repeat="post in posts" >
    <div find-urls link-clicked="itemClicked(link, post)" ng-bind="post.content"><div>
</div>

Controller:

$scope.itemClicked = function(link, post) {
  console.log(link);
  console.log(post);
};

Directive:

function findUrls($compile) {
  return {
    restrict: 'AC',
    scope: {
        linkClickedCallback: '&linkClicked'
    },
    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 linkPatterns = new Array(
        {
          pattern: /(^|[^\/])(www\.[\S]+(\b|$))/ig,
          template: '&nbsp;<a class="absolute_link" href="http://$2" ng-click="linkClickedCallback({link: 1});" 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="linkClickedCallback({link: 1});" 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="linkClickedCallback({link: 1});" target="_blank">$2</a>'
        });

        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);
        }
      }
    }
  };
}

I still need to do some work to capture the link value and pass that along instead of the hard coded "1" but this shows how it needs to be done.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM