Utilizing a function as an argument within two directives in AngularJS

My list comprises of Task items:

This is my template:

<div> 
    <p class="work-item-name">{{ task.Name }}</p>
    <p class="assigned-to">{{ task.Assignee }}</p>
    <button class="btn btn-primary btn-sm" ng-click="goBack()"><i class="fas fa-arrow-left"></i></button>
    <button class="btn btn-primary btn-sm" ng-click="moveForward()"><i class="fas fa-arrow-right"></i></button>
    <button class="btn btn-danger btn-sm" ng-click="removeTask()"><i class="fas fa-trash-alt"></i></button>
</div>

All these are nested within a taskList:

This is the taskList template:

<div id="{{ status }}" class="col-md-4 tasksContainer">
    <ul class="list-group">
    <li class="list-group-item flex-column">To Do</li>
    <li ng-repeat="task in tasks | filter:{Status: 0}" class="list-group-item list-group-item-danger">
            <task-card 
                    task-details="task"
                    go-back-task="goBack()"
                    move-forward-task="moveForward()"
                    remove-task="removeTask()">
            </task-card>
        </li>
    </ul>
</div>

I want to pass on the go back, move forward and delete task functions from the initial call:

<task-List 
    status="todo" 
    tasks="tasks"
    go-back-task="goBack($event, task)"
    move-forward-task="moveForward($event, task)"
    remove-task="removeTask($event, task)">
</task-List> 

to each individual task (in order for each task's button to alter its properties). But in my existing code, on the final call when the button is pressed, both $event and task appear as undefined. What would be the correct approach to passing down functions as parameters in such scenarios?

Answer №1

One possible explanation for the problem is that when the task-list is instantiated, the functions are being called immediately like this

back-Task="backTask($event, task)"
.

Instead of that approach, it would be better to pass references to the functions like so back-Task="backTask" and then call the functions within ng-clicks in the Task template like this

ng-click="backTask($event, task)"

Here is an example of the Task template:

<div> 
    <p class="assignment">{{ task.Assignment }}</p>
    <p class="assignment">{{ task.Assignee }}</p>
    <button class="btn btn-primary btn-sm" ng-click="backTask($event, task)"><i class="fas fa-arrow-left"></i></button>
    <button class="btn btn-primary btn-sm" ng-click="advanceTask($event, task)"><i class="fas fa-arrow-right"></i></button>
    <button class="btn btn-danger btn-sm" ng-click="deleteTask($event, task)"><i class="fas fa-trash-alt"></i></button>
</div>

And here is an example of the Task list template:

<div id="{{ status }}" class="col-md-4 taskList">>
    <ul class="list-group">
    <li class="list-group-item flex-column">To Do</li>
    <li ng-repeat="task in tasks | filter:{Status: 0}" class="list-group-item list-group-item-danger">
            <task 
                    task="task"
                    back-Task="backTask"
                    advance-Task="advanceTask"
                    delete-Task="deleteTask">
            </task>
        </li>
    </ul>
</div>

Lastly, the instantiation of the Task list should look something like this:

 <task-List 
    status="todo" 
    tasks="tasks"
    back-Task="backTask"
    advance-Task="advanceTask"
    delete-Task="deleteTask">
</task-List> 

I hope this explanation helps and makes sense :)

P.S. If you're defining directives, remember to use camel case in the JavaScript declaration (e.g. taskList) and lower-case-dash-separated in the template (e.g. <task-list>).

Answer №2

In order to implement the task component, utilize one-way binding using '<' for inputs and expression binding with '&' for outputs:

app.component("task", {
    bindings: { item: '<',
                backTask: '&',
                advanceTask: '&',
                deleteTask: '&'
              },
    controller: function() {
        this.backClick = (event) => this.backTask({$event: event});
        this.advanceClick = (event) => this.advanceTask({$event: event});
        this.deleteClick = (event) => this.deleteTask({$event: event});
    },
    template: 
        `<div> 
            <p class="assignment">{{ $ctrl.item.Assignment }}</p>
            <p class="assignment">{{ $ctrl.item.Assignee }}</p>
            <button ng-click="$ctrl.backClick($event)"><i class="fas fa-arrow-left"></i></button>
            <button ng-click="$ctrl.advanceClick($event)"><i class="fas fa-arrow-right"></i></button>
            <button ng-click="$ctrl.deleteClick($event)"><i class="fas fa-trash-alt"></i></button>
        </div>`
});

Similarly, for the taskList component:

app.component("taskList", {
    bindings: { status: '<',
                tasks: '<',
                backTask: '&',
                advanceTask: '&',
                deleteTask: '&',
              },
    controller: function() {
        this.backClick = (event, task) => backTask({$event:event, $task:task});
        this.advanceClick = (event, task) => advanceTask({$event:event, $task:task});
        this.deleteClick = (event, task) => advanceTask({$event:event, $task:task});
    },
    template:
        `<div id="{{ $ctrl.status }}" class="col-md-4 taskList">
            <ul class="list-group">
            <li class="list-group-item flex-column">To Do</li>
            <li ng-repeat="task in $ctrl.tasks | filter:{Status: 0}" class="list-group-item list-group-item-danger">
                <task 
                    item="task"
                    back-task="$ctrl.backClick($event, task)"
                    advance-task="$ctrl.advanceClick($event, task)"
                    delete-task="$ctrl.deleteClick($event, task)">
                </task>
            </li>
            </ul>
        </div>`
});

Example of usage:

<task-list 
    status="vm.todo" 
    tasks="vm.tasks"
    back-task="vm.backTask($event, $task)"
    advance-task="vm.advanceTask($event, $task)"
    delete-task="vm.deleteTask($event, $task)">
</task-list> 

To explore further details, refer to the AngularJS Developer Guide - Component-based application architecture.

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

When the component mounts in React using firestore and Redux, the onClick event is triggered instantly

I am facing an issue with my component that displays projects. Each project has a delete button, but for some reason, all delete buttons are being automatically triggered. I am using Redux and Firestore in my application. This behavior might be related to ...

Exploring the power of React Hooks with the useState() function and an array filled

When creating new "Todo" items and modifying the fields, everything works fine. However, my problem arises when trying to retrieve the child data after clicking the "show all objects" button. To better understand my issue, here is a code example: const Co ...

Create an array by copying elements from another array object

My goal is to merge the data from two arrays, array1 and array2, into a new array called array3. Here's how I want it structured: array 1 objects: userName, userId array 2 objects: userId, msg I aim to obtain an array3 consisting of: userId, userNa ...

Activating a link click inside a table with jquery

I have been attempting to trigger a click on an anchor within the table compareTable with the code below, however it does not appear to be working as expected. Would anyone be able to provide insight into a possible solution? $('#compareTable a' ...

Angular directive for automatically selecting a <select> value when there is only one option available in ngOptions

How can I create a directive that automatically preselects an option if only one item is available in the ngOptions scope? Currently, my code looks like this: <select id="provider" name="provider" class="form-control" ng-model="foo.provider" ...

What is the best way to link the roll button to a specific video URL?

I am currently working on a project that involves assigning specific videos to 6 roll buttons for continuous play. For instance, I want the first roll button to display a yellow dice and the second button to show a blue dice, and so on. As of now, I have ...

Error occurs when passing a service as a parameter to a controller in AngularJS

After adding 'loginService' as a parameter to the controller in order to reference the service I want to use, I encountered an error that caused the rest of my angular functions to stop working. app.controller('loginController', functi ...

NuxtJs login feature is functional, but encounters an unauthorized 401 error

I am utilizing the NuxtJs auth module to manage my authorization within the application state. I have created an express API specifically for this purpose, and it functions correctly. Below is the configuration included in my nuxt.config.js file: axios ...

Stop Cross-Site Scripting Attacks by Sanitizing jQuery html()

After retrieving data from a database through ajax, I merge it with HTML code on the website using the .html() jQuery function. The process looks like this: $.ajax({ url: "getDatabaseData.php", type: "post", dataType: "json", success: func ...

Reinstall the packages listed in the bower.json file

After updating all the packages in my bower.json file, I decided I want to revert back to the previous versions. I have a backup copy of the old version and I pasted it into the file. Now, how can I install those old versions instead? ...

JavaScript var is not defined

Hey there everyone! I'm facing an issue with this variable in my file. I have a picture, and it's supposed to display a swipe box with some information about the image when the user hovers over it. However, for some reason, the box is not appeari ...

Guide on viewing chromedriver logs during Protractor testing

I've recently discovered that chromedriver has the ability to generate a logfile (https://sites.google.com/a/chromium.org/chromedriver/logging) While the process of setting up this feature when running the executable directly is clear: chromedriver. ...

Ways to identify if a resize event was caused by the soft keyboard in a mobile browser

Many have debated the soft keyboard, but I am still searching for a suitable solution to my issue. I currently have a resize function like: $(window).resize(function() { ///do stuff }); My goal is to execute the 'stuff' in that function on ...

ng-controller does not function properly when assigned a variable as its parameter

Every time I attempt to insert a variable into the ng-controller parameter, I receive the following error message: " Error: [ng:areq] Argument 'curController' is not a function, got string <div ng-include="templates[selected-1]" ng-cont ...

iOS 8 home screen web apps with status bar overlay and footer bar integration

After installing a web application to 'home' and working with it, I noticed that a recent update to iOS has made the usual black status bar transparent and float above the web content below. In addition, there is an unseen horizontal bar at the ...

Performing the addition operation on two floating point numbers in JavaScript

The JavaScript code goes as follows: var receivedamt = parseFloat($('#cashRecText').val()).toFixed(2); console.log(receivedamt); var addon = parseFloat('5.00').toFixed(2); console.log(addon); addon = parseFloat(receivedamt).toFixed(2 ...

Incorporating a dropdown menu into an HTML table through jQuery proves to be a

I loaded my tabular data from the server using ajax with json. I aimed to generate HTML table rows dynamically using jQuery, with each row containing elements like input type='text' and select dropdowns. While I could create textboxes in columns ...

Struggling to decide on the perfect CSS selector for my puppeteer script

I am trying to use puppeteer page.type with a CSS selector. <div class="preloader"> <div class="cssload-speeding-wheel"></div> </div> <section id="wrapper" class="login-register"> <div class="login-box"> <d ...

The event handler is not being triggered when selecting the tag

Currently working on a project where I am utilizing vanilla HTML/CSS/JS. My goal is to hide all items on a page initially, set a default option in a select tag, display only the element with the selected ID, and allow the user to choose different time peri ...

Executing all promises later in Node.js using Promise.all

Having a series of promises set up as follows: module.exports = function (a, b, c) { return someAsync(() => { someFunc(a); }) .then(() => myPromises(a, b, c)) .then(result => { console.log(&apos ...