Sending the object context back to the controller callback from an AngularJS Directive

I am currently working on creating a modified version of ng-change with a delay feature for auto-saving changes.

Here is the custom directive I have implemented:

myApp.directive('changeDelay', ['$timeout', function ($timeout) {
    return {
        restrict: 'A',
        require: 'ngModel',
        scope: {
            callBack: '=changeDelay'
        },
        link: function (scope, elem, attrs, ngModel) {
            var firstRun = true;
            scope.timeoutHandle = null;

            scope.$watch(function () {
                return ngModel.$modelValue;
            }, function (nv, ov) {
                console.log(firstRun);
                if (!firstRun) {
                    console.log(nv);
                    if (scope.timeoutHandle) {
                        $timeout.cancel($scope.timeoutHandle);
                    }
                    scope.timeoutHandle = $timeout(function () {
                        //How can I pass person??
                        scope.callBack();
                    }, 500);
                }
                firstRun = false;
            });
        }
    };
}]);

And this is the controller for it:

myApp.controller('MyCtrl', ['$scope', function ($scope) {
    $scope.people = [{
        name: "Matthew",
        age: 20
    }, {
        name: "Mark",
        age: 15
    }, {
        name: "Luke",
        age: 30
    }, {
        name: "John",
        age: 42
    }];

    $scope.updatePerson = function (person) {
        //console.log("Fire off request to update:");
        //How can I get person here??
        //console.log(person);
    };

}]);

This HTML markup should allow for specifying the controller scope method and the object to be passed to it:

<div ng-app='myApp'>
    <div ng-controller="MyCtrl">
        <div ng-repeat="person in people">
            <input type="text" ng-model="person.name" change-delay="updatePerson(person)" />
        </div>
    </div>
</div>

Here is the failing fiddle link for reference: http://jsfiddle.net/Troop4Christ/fA4XJ/

It seems that I am struggling to figure out how to pass the "person" parameter to the directive attribute.

In summary, my goal is to replicate the functionality of ng-change with some modifications. How can this be achieved using ng-change?

Answer №1

Solution

It is important to remember that when using isolate scope binding in AngularJS directives, the correct syntax to use is "&" instead of "=". This will ensure that scope.callBack() correctly executes the updatePerson(person) function.

Explanations

When working with isolate scope, you have three options: "@", "=", and "&":

  • "@" instructs Angular to watch the result of attribute evaluation against the element scope
  • "=" tells Angular to create a getter/setter using $parse
  • "&" indicates that Angular should bind a function that evaluates the attribute and optionally extends the attribute definition scope as an argument for the function call.

Choosing the "&" option means that calling callBack() on the isolated directive scope will trigger updatePerson(person) in the outside scope without extending any objects from the isolate scope.

If you wanted to extend the scope, you could have replaced the person argument in the updatePerson(person) function by calling scope.callBack({person: {a:1}}). This would make person equal to {a:1} in the context of the updatePerson function (not the Angular scope).

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

Generating multiple circles on Google Map using ng-maps

I have reviewed several similar posts on SO, but I am still struggling to figure out my mistake. My goal is to place multiple circles on a Google map using a JSON string setup like this: [ {"name":"0","lat":30.45,"long":91.15}, {"name":"1","lat": ...

One creative method for iterating through an array of objects and making modifications

Is there a more efficient way to achieve the same outcome? Brief Description: routes = [ { name: 'vehicle', activated: true}, { name: 'userassignment', activated: true}, { name: 'relations', activated: true}, { name: &apos ...

Do you have any suggestions on how to fix this npm SQLite installation issue?

Could use some help with an SQLite installation error I'm encountering. Any ideas on what the issue might be and how to resolve it? C:\Users\jacka\Downloads\discord-emoji-stealer-master\discord-emoji-stealer-master>npm i & ...

Guide on accessing Azure Configuration Application settings in a Node application with JavaScript

Currently, I have a node.js application named "myClient" deployed on Azure as an App Service. Within this setup, I utilize several configuration files that contain specific values tailored to their respective runtime environments: appconfig.json is used f ...

Guide to ensuring every request in an Express.js application contains a cookie

Currently, I am in the process of developing a CRUD application using both React and Node. As part of my development, it is crucial for me to validate whether the cookie is present or not for each request. app.all("*", (req,res) => { // If the cookie ...

Spontaneous Link with JQuery and Colorbox

Just to clarify, I have no programming experience so please explain everything in simple terms. I am currently using a .js script within SharePoint and it's working perfectly! <!DOCTYPE html> <html> <head> <meta charset= ...

Angular.js: automatically select default option based on ID

In my angular.js single page application, I am retrieving initial data from a rest endpoint. The data consists of a list of IDs representing saved models and a tree of options for cascading dropdowns. How can I automatically set the default path in the t ...

Retrieving Remote Headers in Loopback.io Inbound HTTP Method

In my remote method, I have placed the application logic as shown below: module.exports = function(Entity) { HcpEntity.retrieveProfile = function(body, cb) { process.nextTick(function() { //TODO: Add Application Logic here } } } Also, he ...

The problem with document.cookie: Functions properly on localhost but displays as empty when hosted on the web

I have been exploring various resources, but none seem to describe my unique situation. Currently, I am in the process of creating a website using ReactJS for the front-end and NodeJS with Express for the back-end. The production versions are accessible a ...

How can I activate the copy function in jQuery?

I'm trying to figure out how to initiate a copy event using JavaScript or jQuery. I need to be able to simulate the copy event by clicking on a button, but I haven't been able to find a solution yet. I want to avoid using ZeroClipboard or any oth ...

Animating several elements by toggling their classes

I'm struggling to implement smooth animations on this box. I've tried using 'switchClass' but can't seem to keep everything together. Any help would be greatly appreciated. Here is the code snippet for reference: <script src=" ...

What is preventing me from obtaining the select and input values?

I'm currently facing an issue where I am unable to retrieve the values of customInput and customSelect and store them in the state. The challenge arises when trying to integrate these components into a react dashboard material-ui setup. Strangely, whe ...

Exploring Angular.js: Finding the correct path in a JSON array

Within my Angular application, I have a $scope variable defined as follows. $scope.roleList2 = [ { "roleName" : "User", "roleId" : "role1", "children" : [ { "roleName" : "subUser1", "roleId" : "role11", "collapsed" : true, "children" : [ ...

What causes immediately invoked functions within event handlers to be executed before the event is triggered?

let b = (function maria() { alert("ee"); })(); * this code runs as soon as the page loads * <button onclick="b">Click me</button> * this code only runs when button is clicked * <button onclick="alert('ee')">Click m ...

I'm looking for a method in JavaScript that can search through my XML file to locate specific attributes and return the entire parent element containing that attribute. Can anyone help with

I'm completely new to XML and Javascript. I currently have this code in my HTML file: <select id="eigenschaften" name="eigenschaften" type="text" onchange=""> <option value="">Choose Property</option> <option value="soci ...

The problem with the Next.js 14 generateStaticParamsparams parameter is that it is currently

I'm using this documentation as a reference to extract parameters from the URL in my generateStaticParams function: https://nextjs.org/docs/app/api-reference/functions/generate-static-params#generate-params-from-the-bottom-up This is the route I am w ...

Is it acceptable to use JavaScript files in the pages directory in NEXTJS13, or is it strongly advised to only use TypeScript files in the most recent version?

In the previous iterations of nextJS, there were JavaScript files in the app directory; however, in the most recent version, TypeScript files have taken their place. Is it still possible to begin development using JavaScript? I am working on creating an a ...

Exploring the Relationship between Parent and Child Scopes in AngularJS

point 1 I'm perplexed as to why I couldn't access the child controller property using {{$scope.parentcities}}. However, when I simply use {{parentcities}}, it works. Why is it that we cannot write $scope dot and then property name? <div ng-a ...

Can buttons be inserted into an Input control?

I am currently working on developing a custom timepicker that is compatible with both Internet Explorer and Chrome. The desired time format is 'hh:mm'. This is what I have so far: <input ng-model="timeHours" type="number" class="hours" placeh ...

Fetching Information from Firebase and Populating Dropdown Menus on a Website

Displayed below is a code snippet from a .JSON file stored in a Firebase database. "questionnaires" : { "ORANGE" : { "location" : "ny", "major" : { "engineering" : { "ECE" : { "3rd sem" : { "2018 ...