Pass object context back to controller callback from AngularJS Directive
Asked Answered
A

1

1

I'm essentially trying to recreate ng-change but add some delay in it (auto-save on change frequency timeout).

So far, I have the following directive:

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;
            });
        }
    };
}]);

With the following controller:

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);
    };

}]);

And this markup should be able to define which controller scope method to call as well as the object that is 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's an failing fiddle: http://jsfiddle.net/Troop4Christ/fA4XJ/

As you can see, I can't figure out how to call the directive attribute parameter w/ the "person" parameter passed to it.

So like I said, at the begining.. just trying to recreate ng-change w/ some "tweaking". How is this done in ng-change? i.e.

Affectionate answered 20/3, 2014 at 21:46 Comment(0)
C
4

Solution

Isolate scope binding should be declared with "&" instead of "=", thus resulting in scope.callBack() executing the updatePerson(person) given function.

Explanations

When isolating a scope, you work with "@", "=" and "&":

  • "@" tells angular to watch the result of attribute evaluation against the element scope
  • "=" tells angular to build the getter/setter with $parse
  • "&" tells angular to bind a function that will evaluate the attribute (and, as an option, provide an extension to the attribute definition scope as an argument to this function call).

So, when you choose this last option "&", it means that calling callBack() on the isolate directive scope will actually call updatePerson(person) againts the outside scope (not extended with any object coming from isolate scope).

Taking the scope extension capability into account, you could have replaced the person argument of the updatePerson(person) by calling scope.callBack({person: {a:1}}). Then person would have been {a:1} in the updatePerson call scope (function scope, not angular scope).

Caban answered 20/3, 2014 at 22:10 Comment(2)
ok.. so now updatePerson(person) is passed in as a string essentially.. how does person get back passed through as a parameter to scope.callback()? Can't just do this: scope.callback(person); The directive doesn't know what person is.. nor should it.. just like ng-change doesn't know what person is, or, if I just wanted the $index of the ng-repeat.. my directive should be agnostic of the expression passed...Affectionate
Ok.. I take it back.. you were dead right.. not sure how it's working.. but it is.. Thanks! jsfiddle.net/Troop4Christ/fA4XJ/13 Maybe you could explain "why" the & is working?Affectionate

© 2022 - 2024 — McMap. All rights reserved.