Unable to successfully call a directive function from a nested child directive

I'm facing a challenge with utilizing a directive that was created by another developer to notify my directive when the ngRepeat inside of it has completed its creation.

My parent directive has an isolate scope and includes a function within its scope that needs to be triggered by the child directive. Below is the code snippet:

angular.module('my.directives')

.controller('myTableCtrl', function($scope, $element, $attrs) {

    $scope.tableLoaded = function(tableName){
        console.log("Table Loaded");
    };

})

.directive('myTable', function() {
    return {
        restrict: 'EA',
        scope: {},
        controller: 'myTableCtrl as myTable'
    };
})

.directive('repeatDone', function($timeout) {
    return function(scope, element, attrs) {
        if (scope.$last) {
            $timeout(function(){
                scope.$eval(attrs.repeatDone);
            });
        }
    }
});

This is how my HTML appears:

<my-table>
    <div ng-repeat="row in tableRows" repeat-done="tableLoaded('main');"></div>
</my-table>

Prior to adding the {scope:{}}, the myTable directive was encountering confusion when there were multiple tables on the page (triggering the tableLoaded function from the wrong child). Hence, I introduced the isolate scope as a best practice. However, this resulted in the repeated Done directive being unable to access/call the tableLoaded() function within the parent myTable directive.

I would greatly appreciate any assistance provided.

EDIT:

To clarify, tableLoaded() is a function associated with the myTable directive, and I aim to call it from the repeatDone directive, which could be nested several levels deep inside the table directive. Additionally, I do not wish to modify the repeatDone directive or have it acknowledge the existence of the myTable directive.

Answer №1

Check out the solution below for assistance:

    angular.module('my.directives')

    .controller('myTableCtrl', function($scope, $element, $attrs) {

    this.tableLoaded = function(tableName){    //bind the function to controller instead of $scope
        console.log("Table Loaded");
    };

    })

    .directive('myTable', function() {
    return {
        restrict: 'EA',
        scope: {},
        controller: 'myTableCtrl as myTable'
    };
})

.directive('repeatDone', function($timeout) {
    return {
        restrict: 'EA',
        scope: true,  //your child directive might want to inherit stuff from the parent directive's controller maybe 
        require:'?^myTable',  //require the parent directive 
        link: function(scope, element, attrs,tableCtrl) {  
            if (scope.$last) {
                $timeout(function(){
                    tableCtrl.tableLoaded();    
                });
            }
        }
    }
});

Update:

I am considering the scenario where multiple tables may exist concurrently, each with a single repeatDone inside. An approach is to Emit an event upon completion up the scope and capture it in the required controller/directive. Optionally, a unique identifier can be passed for specific handling within a particular controller/directive. Here's an illustration:

.directive('repeatDone', function($timeout) {
    return {
        restrict: 'EA',
        link: function(scope, element, attrs) {
          console.log('in directive');
            var targetUID = attrs.target;
          console.log(targetUID);
            if (scope.$last) {
                $timeout(function(){

                  console.log('repeat-done now');//scope.$eval(attrs.repeatDone);
                    scope.$emit('repeat-done-' + targetUID,{});
                });
            }
        }
    };
});

In your table directive:

.directive('myTable', function() {
    return {
        restrict: 'EA',
        controller: 'myTableCtrl as myTable'
    };
})

And in your table controller:

.controller('myTableCtrl', function($scope, $element, $attrs) {
    console.log('in table Ctrl');
            var self = this;
            $scope.tableUID = $attrs.tableId;
            self.tableLoaded = function(){
                console.log("Table Loaded");
            };
            console.log('tableUID' + $scope.tableUID);
            $scope.$on('repeat-done-' + $scope.tableUID, function(event,args){
              console.log('in catcher function');
                self.tableLoaded();
            });
})

Then utilize:

<my-table table-id="table1">
    <div ng-repeat="row in tableRows" repeat-done target="table1"></div>
</my-table>

For a functional example, visit this JSBIN

Trust this information proves helpful

Answer №2

In my opinion, it could be beneficial to implement ng-transclude on the my-table element in order to utilize internal components effectively.

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

Are there any substitute proxy servers that are capable of bypassing CORS restrictions using local IP addresses?

Successfully bypassing CORS for AJAX requests to public IP addresses using proxy servers has been a game-changer. Is there a similar approach that can be utilized for local IP addresses when the server is hosted off-site? Unfortunately, I lack the abilit ...

"Enhance your website with interactive jQuery lightbox buttons for easy navigation

As I explore the jquery lightbox plugin, I find it to be quite straightforward. However, I am curious if there is a way to make the "previous" and "next" buttons of the plugin function without the images needing to be named sequentially (e.g., "image1.jpg, ...

Trying to showcase information received from a server using an API

For a school project, I am developing a website that can retrieve weather data (currently just temperature) based on a city or zip code from openweathermap.org using an asynchronous call. I have successfully retrieved the data from the API, but I am strug ...

Issue with Angular Reactive form: Checkbox checked property not binding correctly when the page initially loads

Looking to achieve Two-way data binding of Checkbox in Angular Reactive forms. After checking the checkbox, I am updating the 'isdateChkd' variable and storing it in the state. Despite the variable being set to TRUE, the checkbox does not get aut ...

Sort the array by unique ID and retrieve the object with the first and last index

I am working with an array that looks like this: [{ "res": [ '123', 'One', '20210318' ] }, { "res": [ '123', 'One', '20210319' ] }, { "res": [ '123&ap ...

What is the best way to extract a specific number from a table with Selenium, especially when the location remains consistent across all zip

Context: I am attempting to scrape data from a website with JavaScript using Selenium in Python. Goal: Extract a specific number from the table located at 159x26. I believed that this code would retrieve the number from row 159, column 26. Here is the c ...

Preloading and rendering an image onto a canvas in a Vue single-page application is not functioning as expected

I am working on a Vue 3 SPA where I am manipulating canvas elements. To preload my image, I am using the function provided below: async preloadLogo () { return new Promise( (resolve) => { var logo_img_temp = new Image(); const logo_s ...

Incorporate titles for items in the jquery caroufredsel plugin

I am currently using the second example of the caroufredsel plugin, which can be found on this page . I am attempting to add a caption for each picture. To achieve this, I have used `li` and `lis` in my HTML code: <div class="list_carousel"> &l ...

Running a Blitz.js api handler triggers a Google Cloud Storage call failure with the message "error:0909006C:PEM routines:get_name:no start line"

When attempting to utilize @google-cloud/storage within a Blitz.js /api handler, I encounter the following error: error:0909006C:PEM routines:get_name:no start line at Sign.sign (internal/crypto/sig.js:110:29) at NodeCrypto.sign (C:\Users&bsol ...

Utilizing HTML and JavaScript to dynamically switch stylesheets based on the width of

When it comes to using stylesheets for mobile and non-mobile devices, there is a need for different approaches. The idea of comparing browser height and width in JavaScript seems like a good one, but the implementation may not always work as expected. ...

Exploring the Art of Programming SVG

I am thinking about creating a website that is similar to stackoverflow, but with the added feature of allowing answers to include drawings such as schematics. I would like to have a section in the answer form where users can create these schematics with ...

Having trouble with dynamic CSS styles not functioning properly in Internet Explorer?

My issue involves dynamic CSS settings not functioning properly on Internet Explorer: Here is the code snippet causing the problem: <div class="i-storage-bar-chart-bar-container"> <div class="i-storage-bar-chart-bar" ...

Balancing scrolling status in sibling components within React/Redux

Is it possible for a React component to control the scroll position of another sibling component? The main component, known as Parent, includes two child components: List (which contains a scrollable div) and Actions with a button that is meant to control ...

Exploring ways to retrieve global variables within a required() file in Node.js

Imagine having 2 files: main.js, and module.js: //main.js const myModule = require('./module'); let A = 'a'; myModule.log(); //module.js module.exports = { log() { console.log(A); } } After trying to call myModule.log, ...

Presenting a ui-router modal while maintaining the parent state's refresh-free appearance

I have implemented a unique feature in my angular app called modalStateProvider. It allows me to easily have modals with their own URLs. // Implementing the modalStateProvider app.provider('modalState', [ '$stateProvider', function ...

Ways to gradually reveal all elements within a header section

Is there a way to gradually reveal all the components in my header once the window has finished loading by utilizing jQuery's fadeIn function? Below is the pertinent code snippet: HTML <div class="banner"> <header class="header"> < ...

Incorporating Ruby on Rails: Sending a fresh POST request to API and instantly

I'm a beginner in the field of ruby on rails. Our website allows users to search and receive a list of results. Now, I want to incorporate sorting functionality for the results (by price, rating, etc). The API handles the sorting process, so all I ne ...

Transmitting a key-value pair data object to the server-side code-behind aspect

Transferring a key value pair object to the server side codebehind. What is the method to send it from JavaScript? And how can it be received in C# codebehind? Modification 1 <script type="text/javascript"> function ABC() { va ...

What is the reason behind Chrome's automatic scrolling to ensure the clicked element is fully contained?

Recently, I have observed that when performing ajax page updates (specifically appends to a block, like in "Show more comments" scenarios) Chrome seems to automatically scroll in order to keep the clicked element in view. What is causing this behavior? Wh ...

Utilizing "this" in a situation where the function and selector are not combined

When it comes to utilizing this in different scenarios, the results may vary. In example 1, we see that by directly accessing this, we are able to obtain the correct result. $("#my_div").on("click", function () { alert( $(this).attr("id") ) }); Howev ...