Steps to resolve the issue of ng-click not functioning in a recursive directive template

I've encountered an issue with using ng-click within the template of a recursive directive.

Here is the code snippet: https://jsfiddle.net/qxz7506n/

While clicking the 'root load more button' works fine, the 'child load more button' does not function as expected. How can I pass the child object inside the ngclick through the directive to the controller scope and log it in the console?

HTML:

<div ng-app='demoA'>
    <div ng-controller="IndexCtrl">
        <collection collection='tasks' reply-msg="replyMsg(data)" load-more="loadMore()">
        </collection>
    </div>
</div>

Collection Directive:

.directive('collection', function () {
    return {
        restrict: "E",
        replace: true,
        scope: {
            collection: '=',
            member: '=',
            replyMsg: '&',
            loadMore: '&'
        },
        template: "<ul><member ng-repeat='member in collection track by $index' floor='$index + 1' member='member' reply-msg='replyMsg({data: member.name})'></member><li><input type='button' value='load more...' ng-click='loadMore()' /></li></ul>"
    }
})

Member Directive:

.directive('member', function ($compile) {
    return {
        restrict: "E",
        replace: true,
        scope: {
           floor: '=',
           member: '=',
           replyMsg: '&',
           loadMore: '&'
        },
        template: "<li>" + 
                "<div ng-if='member.isReply'>#{{floor}}</div>" + 
                "<div>{{member.name}}</div>" + 
                "<div ng-if='!member.isReply'><input type='button' value='Reply' ng-click='replyMsg({data: member.name})'/></div>" + 
                "</li>",
        link: function (scope, element, attrs) {
            if (angular.isArray(scope.member.children)) {
                element.append("<collection collection='member.children' reply-msg='replyMsg({data: member.name})' load-more='loadMore()'></collection>"); 
                $compile(element.contents())(scope)
            }
        }
    }
})

For example,

When I click the 'root load more button,' it passes through the directive to the controller scope and logs an object including "Europe" and "South America."

Similarly, when I click the 'child load more button,' it should also go through the directive to the controller scope and display an object containing "Italy" and "Spain."

Answer №1

After some adjustments, the issue should be resolved now. Check out the updated JSFiddle for the changes.

The main problem was related to passing the loadMore and replyMsg functions as references to the sub-directives. Instead of invoking them directly like this: load-more="loadMore()", they should be called using ng-click. Additionally, I made a modification changing '&' to '=' in the directives for the passed methods.

HTML

<div ng-app='demoA'>
    <div ng-controller="IndexCtrl">
    <collection collection='tasks' reply-msg="replyMsg" load-more="loadMore">
    </collection>
    </div>
</div>

JavaScript

angular.module('demoA', [])
    .directive('collection', function () {
        return {
            restrict: "E",
            replace: true,
            scope: {
                collection: '=',
                member: '=',
                replyMsg: '=',
                loadMore: '='
            },
            template: "<ul>" + 
                "<member ng-repeat='member in collection track by $index' floor='$index + 1' member='member' reply-msg='replyMsg' load-more='loadMore'></member>" + 
                "<li><input type='button' value='load more...' ng-click='loadMore()' /></li>" + 
            "</ul>"
        }
    })
    .directive('member', function ($compile) {
        return {
            restrict: "E",
            replace: true,
            scope: {
                floor: '=',
                member: '=',
                replyMsg: '=',
                loadMore: '='
            },
            template: "<li>" + 
            "<div ng-if='member.isReply'>#{{floor}}</div>" + 
            "<div>{{member.name}}</div>" + 
            "<div ng-if='!member.isReply'><input type='button' value='Reply' ng-click='replyMsg({data: member.name})'/></div>" + 
            "</li>",
            link: function (scope, element, attrs) {
                if (angular.isArray(scope.member.children)) {
                    element.append("<collection collection='member.children' reply-msg='replyMsg' load-more='loadMore'></collection>"); 
                    $compile(element.contents())(scope)
                }
            }
        }
    })

    .controller('IndexCtrl', function ($scope) {
        $scope.replyMsg = function(data) {
            alert(data);
        };
        $scope.loadMore = function() {
            alert("clicked");
        };
        $scope.tasks = [
            {
                name: 'Europe',
                children: [
                    {
                        name: 'Italy',
                        isReply: true,
                    }, 
                    {
                        name: 'Spain',
                        isReply: true,
                    }
                ]
            }, 
            {
                name: 'South America',
                children: []
            }
        ];
    });

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

Merge the throw new Error statement with await in a single expression

Is it possible to combine throwing an error and using the await keyword in one statement using the AND operator? The code snippet below demonstrates my intention: throw new Error() && await client.end(). So far, this approach has been working wel ...

One the year is chosen, it will be automatically hidden and no longer available for selection

<div ng-repeat="localcost in vm.project.localCosts" layout="column"> <md-select name="localcost_{{$index}}"ng-model="localcost.year" flex> <md-option ng-repeat="years in vm.getYears()" ng-value="years">{{years}}< ...

The makeSVG function from GoJS is failing to generate the correct HTML SVG object

I have been utilizing the Diagram.makeSVG() method to create an SVG from my diagram. Subsequently, I appended the SVG to a new empty tab using this script (diagram represents my Diagram Object): function print() { var newTab = window.open(), svg ...

Creating a Jasmine test for the event.target.click can be accomplished by defining a spec that

I need help creating a Jasmine test spec for the following method in my component. Here is my Component Method methodName(event): void { event.preventDefault(); event.target.click(); } I have started writing a test but don't fully cover event. ...

Angular filter - organizing objects based on a specific property or a combination of properties

I modified the Angular filter group by example by converting the team into an object. var app = angular.module('myApp',['angular.filter']); app.controller('MainController', ['$scope', function($scope){ $sc ...

Is it possible to invoke a JavaScript function from within a CSS file?

Currently, I am focusing on developing responsive web design and looking for ways to avoid creating multiple versions of each page based on screen width variations. The struggle lies in managing font sizes effectively. While attempting to style them using ...

"MongoDB Aggregating Data with Nested Lookup and Grouping

I have 3 collections named User, Dispensary, and City. My desired result structure is as follows: { _id: , email: , birthdate: , type: , dispensary: { _id: , schedule: , name: , address: , phone: , u ...

Switching languages in Nuxt i18n causes the data object to reset

Recently, I incorporated nuxt-i18n into a project to support multiple languages. Everything was running smoothly until I encountered an issue where switching language while filling out a form resulted in all data on the page being lost. To tackle this pro ...

Blue Jay Guarantees: Construct props object on the fly and execute simultaneously

If we take a look at this example: https://github.com/petkaantonov/bluebird/blob/master/API.md#props---promise Promise.props({ pictures: getPictures(), comments: getComments(), tweets: getTweets() }).then(function(result) { console.log(re ...

Challenges arising with the express search feature

Currently, I am in the process of developing an API for a to-do application. I have successfully implemented the four basic functions required, but I am facing some challenges with integrating a search function. Initially, the search function worked as exp ...

The functionality of a generated button has been compromised

My goal is to create a webshop that doesn't rely on MySQL or any database, but instead reads items from JSON and stores them in LocalStorage. However, I've encountered an issue where the functionality of buttons gets lost after using AJAX to gene ...

Trigger a notification based on the selected choice

Here is some sample HTML code: <div id="hiddenDiv" style="display: none;"> <h1 id="welcomehowareyou">How are you feeling today?</h1> <select name="mood" id="mood"> <option value="" disabled selected>How are you feeling?</o ...

Utilize JQuery to Extract HTML Elements

I'm working on developing a Chrome extension and one of my tasks is to extract specific text from the webpage I am currently visiting and store it in a variable. I have been attempting to achieve this using jQuery, however, none of the solutions I&apo ...

Problem with Closing Alerts in Angular UI Bootstrap

Utilizing Angular UI Bootstrap to create Alert boxes, the code used is as follows: <alert data-ng-repeat="alert in alerts" type="{{alert.type}}" close="closeAlert($index)">{{alert.msg}}</alert> The output is as expected: Inquiring: Is there ...

Efficient state management using Context and typescript

Currently, I am exploring the use of context in my development project - a dating app for dogs. As part of this fun endeavor, I need to pass the current user's information throughout the application. However, I am facing challenges with integrating c ...

Having trouble using angular.isString in conjunction with ng-repeat

Is there a way to use angular.isString for comparison within an ng-if in an ng-repeat loop? Currently, all items in the array are being returned. I attempted to simply display the result of angular.isString, but no output is generated. This is my desired ...

retrieve particular content from html following ajax return

Currently, I am in the process of working on ajax functionality where I need to send a request to retrieve data from a specific page. The challenge that I am facing is that the target page contains a complete template with a header, footer, side menu, and ...

Enhancing dynamic checkboxes with mouseover functionality

Can someone help me figure out how to implement a mouseover effect for checkboxes? I want the checkbox to display more information about the subject when someone hovers over it. Here is the code I have for generating dynamic checkboxes, but I'm not s ...

Every time I try to use the SayHello function with the parameter "text", an error pops

let myApp = angular.module('myApp', []); myApp.factory('greetingFactory', function() { return { greet: function(message){ return "Greetings " + message; } } }); myApp.service('greetingService&a ...

Add three rows without clicking, then click once to add one row at a time

Seeking guidance on how to defaultly display 3 rows after adding and removing rows, as well as applying the removal of a default set of 3 rows using JavaScript. Any valuable ideas are appreciated! Example needed:- https://i.sstatic.net/DF8Wn.png $(docum ...