Display a custom AngularJS directive on content loaded through $http request

I'm facing a dilemma. I have created a directive

app.directive('a', function() {
    return {
        restrict: 'E',
        link: function(scope, elem, attrs) {
            elem.on('click', function(e){
                e.preventDefault();
                alert('Hyperlinks not allowed!');
            });
        }
    };
});

and I also have an $http request to fetch JSON data for the page

{
    "currentNodeName":"Page 1",
    "childrenNodes":[
        {"id":"3","name":"Page 1-1"},
        {"id":"4","name":"Page 1-2"}],
    "parentNode":null,
    "currentNodeContent":[
        {"content":"<p>This is Page1. <a href=\"http://badlink.org/i/dont/want/to/work\">Link</a></p>"}],
    "currentNodeId":"1"
}

The content of currentNodeContent is then loaded into a div

<div id="loadedContent" ng-bind-html="boardCtrl.nodeData.currentNodeContent[0].content"></div>

Now, my question is: How can I make sure that the <a> tag in the loaded content functions as a directive?

Thank you.

Answer №1

To get closer to a correct solution, you can refer to the information provided at this Stack Overflow discussion. However, a more efficient approach would involve the following code:

app.directive("secureBind", function($compile) {
    return {
        link: function(scope, element, attrs) {
             scope.$watch(attrs.secureBind, function(newData) {
                  element.html(newData);
                  $compile(element.contents())(scope);
             });
        }   
    };  
});

The ng-bind-html only assigns the data to the html without running $compile on it (refer to this GitHub source). However, this method doesn't inform contained directives when their value changes. A more enhanced version is as follows:

app.directive("secureBind", function($compile) {
    return {
        link: function(scope, element, attrs) {
            var childScope;
            scope.$watch(attrs.secureBind, function(newValue, oldValue) {
                if (!newValue && !oldValue) return; // handle first run
                if (childScope)
                    childScope.$destroy();
                element.html(newValue || "");
                if (!newValue) return;
                childScope = scope.$new();
                $compile(element.contents())(childScope);
            });
        }
    };
});

This aligns with Angular's perspective. Nonetheless, consider the following points:

  • You are deviating from the MVC concept.
  • By restricting elements with directives, you're essentially blacklisting elements, which is generally discouraged. Use a whitelist instead.
  • Allowing user input in your Angular context poses security risks.

A safer practice involves filtering input HTML through a whitelist function before binding it with ng-bind-html.

Answer №2

Angular utilizes 'a' as a directive with a priority set to '0' (https://docs.angularjs.org/api/ng/directive/a)

To tackle this issue, consider the following steps:

  • Increase your priority level beyond the defined value, for instance, try 1 or Number.MAX_VALUE.
  • Enable the terminal option to ensure that lower priorities are not processed.

This approach may just do the trick... :)

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

Using the npm package in JavaScript results in a return value of 1

Recently, I have been working on turning this into an npm package: Test.tsx: import React from "react"; export default class Test extends React.Component { public render() { return ( <h1> Hallo & ...

How can I modify this section of the code in Google Script to retrieve all columns?

My question is, how can I modify this code to fetch all columns from the array instead of just [0,1,2,3] Here is the line of code in question: const new_table = [0,1,2,3].map(x => make_row_from_col(this_table, x)).join('\n'); Using obje ...

Always display all options in MUI Autocomplete without any filtering

I am seeking to eliminate any filtering in the MUI Autocomplete component. My goal is for the text field popper to display all available options. The results are obtained from a server-side search engine. These results, or "hits," already provide a filter ...

Angular UI-Select's issue with duplicating tags while adding objects for tagging functionality

I have implemented the ui-select library to enable the "Tagging" feature in my project. Currently, I am utilizing an Array of objects where each object contains an id and a name. The functionality is working as expected. However, when a user types in a n ...

Creating an anonymous component in Vue.js involves enclosing the received slots (vnodes) within a wrapper component

Is there a way to wrap two specified named slots, slotOne and slotTwo, which are located in the child component at this.$scopedSlots.slotOne and this.$scopedSlots.slotTwo respectively? I would like to then conditionally render these slots (vnodes) as shown ...

Both the maxlenght and ng-maxlength directives appear to be ineffective in AngularJS

In my HTML file, I have the following input: <input name="password" id="newPasswordConfirmation" ng-model="newPasswordConfirmation" type="number" inputmode="numeric" placeholder="" required ...

Attempting to input a parameter into a personalized directive

Currently developing a small search application using Elasticsearch and AngularJS. The app consists of 2 pages: home and results page. However, I am encountering an issue with my custom search directive where I need to pass the value of a service into it. ...

What could be causing the malfunction of this Ajax conditional dialog?

Can anyone help me troubleshoot this code? I've been trying to fix it for a while now, making multiple changes, but still can't find the solution. If you have any ideas please let me know, I haven't seen any errors in the console. The fir ...

Using the result of one function in another function when using async await

I am facing an issue with running a function based on the return value of another function: // in utils.js methods:{ funcOne(){ // do some thing return true } } //in component.vue methods:{ funcTwo(){ let x = this.funcOne() if(x){ ...

Could somebody clarify the situation with the `push` function?

Something seems off with the behavior of the push method. Instead of pushing to only one index within the forEach, it appears to be pushing to all three indexes. Can anyone see what might be causing this unexpected result? let arrayToReduce = [ [ 1, 2, ...

What is the process for spawning a terminal instance within a NodeJS child process?

I'm in the process of setting up a discord channel to serve as an SSH terminal. This involves using a NodeJS server to establish the connection. A custom command will then be used to spawn a new terminal instance that can function as a shell. However ...

A program designed to access and retrieve a universal variable

It seems like a simple task, but I can't seem to figure it out. I'm trying to assign the currentUserId within the getCurrentUser function so that I can use it in other functions. Currently, the code below is returning undefined. What am I overl ...

Incorporating a computed variable in a v-select within a VueJs endless loop

I've been attempting to utilize a computed value in a v-select component from Vuetify, but every time I select an item, it triggers an endless loop. To demonstrate the issue, I have recreated my code in this CodePen. Please be cautious as it may caus ...

Error 403 occurs after submitting the form

Recently, I encountered a 403 error when attempting to submit the form on this page. Interestingly, when I directly accessed the new page by typing the URL into my browser, it loaded without any issues. The PHP code in the initial page looks like this: & ...

Personalizing the React Bootstrap date picker

I am currently working on customizing the react-bootstrap-daterangepicker to achieve a specific look: My goal is to have distinct background colors for when dates are selected within a range and when the user is hovering over dates to make a selection. I ...

MongoDB Sorting Techniques

I'm struggling to figure out how to retrieve an ordered list from MongoDB data. I need to fetch the results from a Mongo collection using return and .find(), structured like this: For instance, let's say I have one collection for cars with 10 do ...

Is it possible for a JavaScript environment to restore function normally after modifying the [[Prototype]] of an object?

After thoroughly reviewing the MDN disclaimers and warnings, as well as an enlightening discussion in a popular online forum, I still find myself seeking answers. This question arose from a previous exchange, which can be found here. Imagine if I were to ...

Preventing users from copying and pasting information from my form by implementing javascript restrictions

I'm looking for a solution to prevent users from copying and pasting in my form using JavaScript. I want to restrict the ability to paste or copy any content into the form. Any assistance would be greatly appreciated! ...

I constantly encounter the error message "Unable to access properties of undefined (reading 'map')"

I am in the process of using Nextjs 13 for developing my front end and I have a requirement to fetch a .json file from a URL and utilize it to populate my website through server side rendering. However, I keep encountering an error saying "Cannot read prop ...

knockout, loop within a loop

Imagine I have a group of Humans who own Cats, and those Cats have Kittens class Person { String name; Cat[] cats; } class Cat { String name; Kitten[] kittens; } class Kitten { String name; } Now I want to display all my Kittens with ...