Passing arguments from an Angular directive to a controller function within an element's HTML

Is there a way to pass the URL of an anchor tag in the directive to the controller function "itemClicked"? The code below successfully logs the "post" object when clicked.

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

Answer №1

Implementing this functionality is a breeze using $scope.$emit and $scope.$on.

If you want to pass a URL from your directive:

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

In your controller, you can listen for the event like this:

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

Answer №2

After some troubleshooting, I realized that the key element I was overlooking was how to properly pass arguments to the linkClickedCallback function in the controller. It's essential to pass the arguments as an object {arg1: 5, arg2: 10} and then include them in the function call within the HTML in the correct order to transmit them to the controller.

To address this issue, I created an object {link: 1} to be passed into linkedClickedCallback with a hardcoded value of 1. The output of the example now displays the value 1 followed by 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 have some refining to do in terms of capturing and passing dynamic link values instead of a static "1," but this demonstration lays out the necessary steps for achieving this goal.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Obtaining the clicked element within a functional component in React

I'm having trouble in React because I am unable to select the clicked element. The use of "this" in a functional component is not functioning as expected. function Test(data) { function getElement() { } return ( <div> ...

A single feature designed to handle various elements

I currently have this HTML code repeated multiple times on my webpage: <form class="new_comment"> <input accept="image/png,image/gif,image/jpeg" id="file" class="file_comment" key=comment_id type="file" name="comment[media]"> <spa ...

The touch events are not detected on Pixi.js when buttons are placed on a stage that has been both scaled and

Currently, I am developing a game using pixi js. In order to ensure that the game appears consistent on all screens, I have implemented the following scaling logic: this.scale = Math.max(this.viewWidth, this.viewHeight) / (2048 * this.ratio); Additionall ...

Tips on successfully transferring a JavaScript variable from PHP to JavaScript

I am struggling with how to manipulate a JavaScript variable in my HTML script and then pass it to a PHP file for incrementing by 1. However, I am unsure of how to return this modified variable back to the HTML file for display. Additionally, I am uncertai ...

Streamline retrieval of alphanumeric indexing within json

When accessing json data using jquery, I came across an index structure like this: data.rows[0].student_1 data.rows[0].student_2 data.rows[0].student_3 and so on... Now, I'm looking to automate this process by creating a loop that allows me to acces ...

After modifying the select option, the input field remains disabled

I successfully developed a self-contained code snippet that toggles the enable/disable state of input fields. It works flawlessly on my HTML page. Check it out below: Identification Type: <select name="Identification-Type" id="Identification-Type"& ...

javascript The final position achieved through requestAnimationFrame is never precise

let pf = document.querySelectorAll('.pf'); for (let i of pf) { Object.assign(i.style, { left: '400px' }) } function shiftLetters() { let start = performance.now(); let dist = -400; let dur = 500; const logoAnimate = ( ...

TypeError: Unable to access the 'classify' property of an object that has not been defined (please save the ml5.js model first)

In my React app, I have set up ml5.js to train a model by clicking on one button and make predictions with another. However, I encounter an error when trying to test the model for the second time: TypeError: Cannot read property 'classify' of und ...

When passing parameters through a URL in TypeScript, the display shows up as "[object object]" rather than as a string

Hey there! I'm trying to pass some string parameters to my URL to fetch information from an API. Everything seems fine, and when displayed in an alert, the URL looks exactly as it should (no [object, object] issue). var startDate = "2020-09-20"; var ...

Using JavaScript to toggle the visibility of grids depending on the radio button choice and then triggering this action by clicking on the search button

As a newcomer to AngularJS development, I am encountering some challenges while attempting to implement the following scenario. Any suggestions or guidance would be greatly appreciated. I aim to showcase either one or two Angular UI grids based on the rad ...

In Javascript, when trying to call Firebase database child(), it may sometimes result in the return value being "

Here is the current setup: Firebase Database: setores: { -KkBgUmX6BEeVyrudlfK: { id: '-KkBgUmX6BEeVyrudlfK', nome: 'test' } -KkDYxfwka8YM6uFOWpH: { id: '-KkDYxfwka8YM6uFOWpH', nome ...

Clicking on the menu in mobile view will cause it to slide upward

I have implemented sticky.js on my website and it is working well. However, when I resize the browser to mobile view and click the main menu button, it goes up and I am unable to close it. I have to scroll up to see it again. How can I make it stick to the ...

Functionality of Ajax: Data fields containing numerous values

I'm confused about the data fields in the ajax function. Typically, the syntax for an ajax function looks something like this: $.ajax({ url: "/aaa/bbb/ccc", method: "SomeMethod", data: someData, success: function (res ...

Webpack 2.7.0 throws an error: "Unexpected parameter: theme"

At the moment, I am on webpack 1.16.0 and using --theme as an argument to set the output path and plugin paths. The command appears as: rimraf dist && webpack --bail --progress --profile --theme=<name of theme> However, as I try to upgrade ...

Troubleshooting issues with NodeJS and Express authentication middleware functionality

I am currently working on implementing the isUserAuthenticated function to run on every server request. This function is required in the app.js file and utilized using app.use(authenticate.isUserAuthenticated). In my project, there is an /authenticate rou ...

Using parseFloat in JavaScript for German number formatting

Currently, I am working on incorporating a Vue.js component that is inspired by the example provided in this link: https://jsfiddle.net/mani04/bgzhw68m/. This is the structure of my source code: computed: { displayValue: { get ...

What methods can be used to construct components using smaller foundational components as a base?

Is there a more elegant approach to constructing larger components from smaller base components that encompass common functionalities, akin to an interface in the OOP realm? I'm experimenting with this concept, but it feels somewhat inelegant. Repor ...

Utilize the https://angular-translate.github.io/ website for translating text

I have been utilizing the module to handle translations. The array of keys I am using is: $scope.array = [ "full_name", "email", "phone_no" ]; For translation, my key-value pairs are set as follows: $translateProvider.translations('en ...

Ways to pass a message from index.html to a Vue.js 3 instance

Picture this scenario: You have a Vue index.html file that also loads a custom script: <!DOCTYPE html> <html lang="en"> <head> ... ... <script type="text/javascript"> languagePluginLoader.then(fun ...

The "Open in new tab" feature seems to be missing for links when using Safari on iOS

My webapp contains links structured like this: <a href="/articles/">Articles</a> I am using JavaScript to control these links within my app: $(document).on("click", 'a', function(ev) { ev.preventDefault(); ev.stopPropagat ...