AngularJS directive scope and $compile - issue with variable not displaying any value

Encountering a small challenge with Angular that is puzzling me. I have a feeling it may be related to scope, but I'm not entirely certain.

Here is the snippet of my HTML:

<i class="icon-question-sign" popover data-placement="top" data-trigger="hover" data-title="Top 10 clients" data-content-compile="<ul><li ng-repeat='client in user.clients | limitTo: 10'>{{client}}</li></ul>"></i>

This is how my directive looks:

app.directive('popover', function($timeout, $compile) {
var linker = function (scope, element, attrs) {
    $timeout(function() {
        var content = $compile(element.data('content-compile'))(scope);
        element.popover({
            'html': true,
            'content': content
        });
    }, 200);
}

return {
    restrict: 'A',
    link: linker
}

});

The outcome correctly repeats the li's for the appropriate length of {{user.clients}}, but fails to render {{client}}. Strangely, it appears empty even though it holds a string value and works when directly added to the HTML without going through the directive. Here is how it currently displays in the DOM:

<ul class="ng-scope"><!-- ngRepeat: client in user.clients | limitTo: 10 --><li ng-repeat="client in user.clients | limitTo: 10" class="ng-scope"></li><li ng-repeat="client in user.clients | limitTo: 10" class="ng-scope"></li><li ng-repeat="client in user.clients | limitTo: 10" class="ng-scope"></li><li ng-repeat="client in user.clients | limitTo: 10" class="ng-scope"></li><li ng-repeat="client in user.clients | limitTo: 10" class="ng-scope"></li><li ng-repeat="client in user.clients | limitTo: 10" class="ng-scope"></li><li ng-repeat="client in user.clients | limitTo: 10" class="ng-scope"></li><li ng-repeat="client in user.clients | limitTo: 10" class="ng-scope"></li><li ng-repeat="client in user.clients | limitTo: 10" class="ng-scope"></li><li ng-repeat="client in user.clients | limitTo: 10" class="ng-scope"></li></ul>

If I substitute {{client}} with something like {{user.email}}, it displays correctly.

I'm unsure of what the issue might be - perhaps I'm overlooking something obvious!

Answer №1

The solution to the issue lies in its root cause: {{client}} in data-content-compile is compiled before the directive triggers, causing client to be undefined in the controller context. The current string passed into $compile looks like this:

<ul><li ng-repeat='client in user.clients | limitTo: 10'></li></ul>

To avoid this situation, the template needs to be passed into the directive in a different manner. Here are some possible approaches:

  1. Store the template as a string in the controller (although not the most elegant solution).
  2. Store the template in a separate file and retrieve it from $templateCache.

I have provided an example using the second approach in this demo:

<div ng-controller="ctrl">
    <script type="text/ng-template" id="client.html">
        <div><ul><li ng-repeat='client in user.clients'>{{client.name}}</li></ul></div>
    </script>
    <i
        popover
        class="glyphicon glyphicon-user"
        data-placement="bottom"
        data-trigger="hover"
        data-title="Top 10 clients"
        data-content-template="client.html"
    ></i>
</div>
angular.module("app", [])
.controller("ctrl", function($scope, User) {
    $scope.user = User;
})
.directive("popover", function($compile, $timeout, $templateCache) {
    return function(scope, el, attr) {
        $timeout(function() {
            el
            .popover({
                html: true,
                content: $compile($templateCache.get(attr.contentTemplate))(scope)
            })
            .popover("show")
        });    
    };
})
.value("User", {
    clients: [
        { name: "John", age: 22},
        { name: "Ann", age: 13},
        { name: "Maria", age: 62},
        { name: "Ivan", age: 44}
    ]
});

Answer №2

It turns out that the solution to my issue was simpler than I had anticipated. I made a slight adjustment to my directive as follows:

// popover
app.directive('popover', function($timeout, $compile) {
    var linker = function (scope, element, attrs) {
        var content = $compile(element.data('content-compile'))(scope);
        $timeout(function() {
            element.popover({
                'html': true,
                'content': content
            });
        }, 800); // Doubled the $timeout duration here
    }

    return {
        restrict: 'A',
        link: linker
    }

});

The key change I made was increasing the $timeout duration and moving the compiled variable outside of it to ensure it is compiled before being called. This tweak seems to have resolved the issue in testing.

While this solution worked for me, it may not be applicable in all cases. If you encounter a similar problem, consider this solution cautiously.

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

Adding null at the end of a JSON encoded PHP array

During the debugging process, this is the data being sent to my javascript: header("Content-Type: application/json"); //echo json_encode($full_product_list); echo json_encode(array()); Below is my ajax call: jQuery.get( "non public api sorry ") ...

Discovering Transcluded Content in an AngularJS Directive

I am attempting to develop an AngularJS directive with the following features: encloses any type of content within adds a substitute content if no transcluded content is provided ...however, I am struggling to find a method to ve ...

What is the proper way to implement v-model for a custom component within the Vue render function?

Below is the code that I am working with: ... var label_key_map = { a: "1", b: "2", c: "3", d: "4" } render: (h) => { var form_data = {} for (let key in label_key_map) { var form_item = h( 'FormItem', {props: {prop: key}}, ...

Switching on and off a class in Next.js

I'm a beginner with Next.js and React framework. My question is regarding toggling a class. Here's my attempt in plain JS: function toggleNav() { var element = document.getElementById("nav"); element.classList.toggle("hidde ...

Flask fails to recognize JSON data when transmitted from Nodejs

I am encountering an issue when trying to send JSON data from Node to Flask. I am having trouble reading the data in Flask as expected. Despite attempting to print request.data in Flask, no output is being displayed. Additionally, when I tried printing req ...

Is it possible to toggle the content of a post within a "post" title on a webpage?

I am currently working on a project where I want to display all "posts" titles on a specific page. When someone clicks on a post title, the content should toggle below it. If the title is clicked again, the content should hide. With the help of the WP-Arc ...

Perform a MongoDB find() query using the _id field as the search criteria

So I am currently working on my express app and I need to find data based on the _id field in MongoDB. Below is a snippet of my MongoDB record: { "_id": { "$oid": "58c2a5bdf36d281631b3714a" }, "title": "EntertheBadJah" ...

Indicate the node middleware without relying on the port number

My website is hosted at mywebsite.com and I am using node and express for middleware services, pointing to mysite.com:3011/api. The website is hosted statically on Ubuntu 16 (Linux) and the middleware is run separately using pm2 (node server). I want to b ...

Strikeout list on click of a mouse

Is there a way to apply strikethrough formatting to text with just a mouse click? The CSS for lists is beyond the form field margin. I've tried multiple methods without success. No matter how many times I change the code, I can't seem to get it r ...

Ensure to execute the controller function immediately following its creation within Angular

Recently, I ventured into the world of AngularJS and successfully created a modal following the instructions on http://angular-ui.github.io/bootstrap/. The modal pops up when a button is clicked. However, there's a twist - I need this modal to open au ...

The AJAX POST form consistently submits data from the initial entry in the list

Upon investigation, I have discovered that the issue is linked to my AJAX posting method. When I submit the form using the standard method (action=""), it successfully populates my database based on the selected record from the list. However, when I util ...

Display a dropdown menu for ngx-chips when the input field is selected

Currently, I am utilizing ngx-chips to generate a tag input for Angular 8. While I have successfully set it up, I am interested in having the dropdown display whenever I focus on the tag itself. At present, the dropdown only appears when I focus on the inp ...

AngularJS users are experiencing issues with the "See More" feature not functioning as expected

One of my tasks involves dealing with a block of text that needs to be truncated using ellipsis. To achieve this, I am utilizing jquery dotdotdot. For more information on dotdotdot, please refer to the documentation. I have created a straightforward dire ...

indexing into a nodelist results in an undefined value

In my current code snippet, I am using the following: const modelInputs = document.getElementsByName('jpd-model') console.log(modelInputs) This code returns a NodeList of all the matching elements. However, if I modify the code to this: const m ...

When attempting to send an email using the emailjs.send function, an unexpected error occurred showing the URL https://api.emailjs.com/api/v1.0/email/send with a

import emailjs from 'emailjs-com'; async function sendEmail() { try { const serviceID = '...'; const templateID = '...'; const userID = '...'; const emailParams = { to_email: '...&a ...

What's the deal with the Conditional changeDetectionStrategy in Angular?

I am working with a card component in Angular: https://i.sstatic.net/oCrEx.png One important feature of this card component is the rating stars, which are displayed as a separate component. However, in this specific scenario, the user is unable to inter ...

The JQuery File-Upload plugin remains inactive even after a file has been chosen

I am currently working on integrating the JQuery File-Upload plugin (). The issue I'm facing is that it doesn't respond when a file is selected. Here are some potential problems to consider: No errors appear in the Chrome console. Selecting a ...

What is the best way to loop through ng-models in an ng-repeat using an Angular controller?

As a beginner in web development, I am currently experimenting with Angular and may make some mistakes along the way. One issue I am facing is setting a model variable within a child ng-repeat when clicking on a checkbox in the parent ng-repeat. I'm u ...

Injecting modules dynamically in AngularJS

Is it possible to dynamically perform dependency injections? For example, injecting modules later rather than when creating the root app? I have a website where I want to create one all-encompassing ng-app instead of having separate ng-apps for different ...

Tips for adding React components to an array with the help of backticks

Currently, I am attempting to populate an array with icons by extracting the name from data and concatenating "<" and "/>" around it in order to convert it into an Mui Icon. Despite renaming the imported icons to match the names in the data, when I ...