Transferring variables from the existing scope to a compiled directive

I'm having trouble passing an object from the current scope to a directive that I added using the $compile service.

While I can successfully pass a string to the child directive, I'm unable to pass the actual object.

Take a look at this fiddle for the scenario : http://jsfiddle.net/ewx2trvx/2/

HTML:

<section ng-app="myApp" ng-controller="MainCtrl">
    <addbuttonsbutton></addbuttonsbutton>
    <div id="space-for-buttons"></div>
</section>

JS:

var myApp = angular.module('myApp', []);

function MainCtrl($scope) {
    $scope.count = 0;
}

myApp.directive("addbuttonsbutton", function () {
    return {
        restrict: "E",
        template: "<button addbuttons>Click to add buttons</button>"
    }
});

//Directive for adding buttons on click that show an alert on click
myApp.directive("addbuttons", function ($compile) {
    return function (scope, element, attrs) {
        element.bind("click", function () {
            scope.count++;
            angular.element(document.getElementById('space-for-buttons'))
                .append($compile("<alert alert='count'></alert>")(scope));
        });
    };
});

//Directive for showing an alert on click
myApp.directive("alert", function () {
    return {
        template: "<div><button class='btn btn-default'>Show alert # {{count}}</button></div>",
        scope: {
            a: '@alert'
        },
        replace:true,        
        link: function (scope, element, attrs) {
            element.bind("click", function () {
                console.log(scope.a);
                alert("This is alert #" + scope.a);
            });
        }
    };
});

Any insights or suggestions?

Thank you.

Answer №1

Firstly, make sure to apply scope after compiling and appending, as you are manipulating the DOM outside of the digest loop:

element.bind("click", function () {
    scope.count++;
    angular.element(document.getElementById('space-for-buttons'))
        .append($compile("<alert alert='count'></alert>")(scope));
    scope.$apply();
});

Also, if you are using alert='count', adjust the scope configuration in the alert directive like so:

scope: {
    a: '=alert'
},

If you opt for a: '@alert', remember to interpolate it in the attribute: alert='{{count}}'

Furthermore, since it involves two-way data binding, consider assigning an additional intermediate primitive property to serve as the button's index:

myApp.directive("alert", function () {
    return {
        template: "<div><button class='btn btn-default'>Show alert # {{index}}</button></div>",
        scope: {
            a: '=alert'
        },
        replace:true,        
        link: function (scope, element, attrs) {
            scope.index = scope.a;
            element.bind("click", function () {
                alert("This is alert #" + scope.index);
            });
        }
    };
});

Check out the demo here: http://jsfiddle.net/ewx2trvx/3/

Answer №2

To ensure proper data interpolation, it is important to pass the value rather than letting Angular assume it should be treated as a string.

Revise your

$compile("<alert alert='count'></alert>")(scope)
to
$compile("<alert alert='{{count}}'></alert>")(scope)
and then convert the received string into a number using: var count = +scope.a;.

In addition, within your template, update {{count}} to {{a}} due to the isolated scope in this case.

It's worth noting that one-time-binding is not available in Angular 1.2. If you are working with version 1.3 or later, you can achieve one-time-binding with {{::count}}.

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

Customize your Shopify Messenger icon using JavaScript!

Shopify recently introduced a new feature that allows customers to contact store owners through messenger. My client has requested me to customize the appearance of this icon with their branded icon instead. https://i.stack.imgur.com/uytpd.png I have not ...

The customized message for parsley's minimum length is not being applied properly when passed as an option during binding

When attempting to bind the Parsley script to an input field, I am encountering an issue with the minlength message not displaying my custom one. Instead, the default error message from Parsley is being shown. I've tried adjusting the code but it does ...

"Combining jQuery and JavaScript to handle form submissions in un

What happens when you combine the Javascript onSubmit handler and jQuery submit handler? <form action="" method="post" onSubmit="myJavascriptHandler();"> <input type="submit" /> </form> <script type="text/javascript"> $("form") ...

Limiting the number of promises in AngularJS

My web application allows users to select multiple files using a file input. After the user selects the files, I upload them one by one through my REST API. However, in Internet Explorer, if the user selects more than 10 files at once, some of the requests ...

"Enhance Your Website with Javascript: Combining and Incorpor

I'm struggling to assign the selected attribute to the option value that is already rendered within the object. However, despite the values being equal, the selected attribute is not being added. Could this issue be related to the appending process? ...

Unable to load custom package in Angular 2 testing environment

I've been following the official Angular 2 testing guide on an existing project. Everything runs smoothly when I use my custom library, downloadjs, in the application. However, I encounter an error in the console during test execution: "__zone_symbol ...

What could be causing the unexpected behavior of angular.isNumber()?

I'm encountering an issue with AngularJS's angular.isNumber, as it doesn't seem to work with strings that represent numbers. Is there a mistake on my end? Would utilizing isNaN() be a better approach? angular.isNumber('95.55') == ...

Ways to fix npm error requiring a suitable loader

I was working on a Vue.js project with vue-chartjs and encountered an issue. I attempted to reinstall the library, but the error persisted: error in ./node_modules/chart.js/dist/chart.esm.js Module parse failed: Unexpected token (6613:12) You may need an ...

Send a PHP object to JavaScript using AJAX

I have a PHP script that successfully uploads a video to the Microsoft Azure service using an API. The API returns a StdObject file, which I then want to send back to JavaScript via AJAX. However, when I try to access the "asset" object in JavaScript, it a ...

405 - Sorry, this method is not allowed for deletion

The issue at hand involves a Spring RESTful web service and a client. When attempting a DELETE request on the server, the following error is encountered: -> DELETE http://localhost:8080/employee/3/logout 405 (Method Not Allowed) Despite implementing th ...

Is it possible to retrieve information from a json file?

I am looking to extract specific elements from a JSON response fetched using the YouTube API. Here is an example of the response I receive in my script: { "version": "1.0", "encoding": "UTF-8", "feed": { // Details of the feed... } } My goal ...

Utilizing AJAX alongside a checkbox

I'm a beginner in the world of AJAX and JavaScript, but I have taken up the challenge of sending a value based on an HTML "" tag using Ajax to a Python handler. Below you will find my code, inspired by this site. The issue I am facing is understanding ...

Text displaying as actionable icons

In my React project, I am utilizing material-table (https://material-table.com/#/) and have successfully imported the necessary icons. However, when viewing the action bar, the icons are displaying as plain text instead of the Material Icon. import React, ...

Enhancing an array item with Vuex

Is there a way to change an object within an array using Vuex? I attempted the following approach, but it was unsuccessful: const state = { categories: [] }; // mutations: [mutationType.UPDATE_CATEGORY] (state, id, category) { const record = state. ...

Can someone explain why the console.log(items) command seems to be executing twice

Item.find() .then(function (items) { if (items.length === 0) { Item.insertMany(defaultItems) .then(function () { console.log("Successfully Saved"); }) .catch(function (err) { console.l ...

Issues with React-markdown, including malfunctioning gfm tables and various other difficulties

My journey to render markdown in react using the react-markdown library has hit a few bumps along the way. I've encountered 2 issues and have been pondering 1 question that remains unanswered: Upon implementing the remark-gfm plug-in, the tables fail ...

Utilizing Gulp variables to create dynamic destination file names?

As a newcomer to gulp, I am curious about the feasibility of achieving my desired outcome. Here is the structure of my projects: root | components | | | component_1 | | styles.scss | | actions.js | | template.html | | ... | componen ...

What is the best way to add data to a URL in an ActionResult Method using window.location.href?

I am having trouble understanding how to retrieve data using window.location.href = '/Product/Success/'+data.OrderTrackNo+'';. I am able to get data using ajax, but it seems different when retrieving data with window.location.href, whic ...

How can I delete an item from an array when I click on a selected element using Material React Select Multiple?

I found this helpful CodeSandBox demonstration that walks through how to implement a multiple material select feature. Here is an array containing all the available options: const permissionsGroupList = [ { name: 'Sellers' }, { name: &a ...

Having trouble with my getJSON function, can't pinpoint the error in my code

After collaborating with some fellow stack users, I have developed the following: http://jsfiddle.net/9ywLq/ I am looking to integrate an external json file in order to achieve something similar to this: http://jsfiddle.net/RCB9M/ Currently, I am linki ...