Передать контекст объекта обратно в обратный вызов контроллера из директивы AngularJS

По сути, я пытаюсь воссоздать ng-change, но добавляю в него некоторую задержку (автоматическое сохранение при тайм-ауте частоты изменения).

Пока у меня есть следующая директива:

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

Со следующим контроллером:

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

}]);

И эта разметка должна определять, какой метод области действия контроллера вызывать, а также объект, который ему передается:

<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>

Вот неисправная скрипка: http://jsfiddle.net/Troop4Christ/fA4XJ/

Как видите, я не могу понять, как вызвать параметр атрибута директивы с переданным ему параметром «человек».

Итак, как я уже сказал, в начале ... просто пытаюсь воссоздать ng-change с некоторыми «настройками». Как это делается в ng-change? то есть


person RavenHursT    schedule 20.03.2014    source источник


Ответы (1)


Решение

Привязка изолированной области должна быть объявлена ​​с помощью "&" вместо "=", что приводит к scope.callBack() выполнению заданной функции updatePerson(person).

Пояснения

При изоляции области вы работаете с «@», «=» и «&»:

  • «@» сообщает angular, что нужно следить за результатом оценки атрибута в отношении области действия элемента.
  • «=» сообщает angular о необходимости создания геттера/сеттера с помощью $parse
  • «&» указывает angular связать функцию, которая будет оценивать атрибут (и, как вариант, предоставить расширение области определения атрибута в качестве аргумента для этого вызова функции).

Таким образом, когда вы выбираете эту последнюю опцию «&», это означает, что вызов callBack() в области действия директивы изоляции фактически вызовет updatePerson(person) снова во внешней области (не расширенной ни одним объектом, поступающим из области изоляции).

Принимая во внимание возможность расширения области действия, вы могли бы заменить аргумент person функции updatePerson(person) вызовом scope.callBack({person: {a:1}}). Тогда person было бы {a:1} в области вызова updatePerson (область функции, а не angular scope).

person lib3d    schedule 20.03.2014
comment
хорошо .. так что теперь updatePerson(person) передается как строка по существу .. как человек возвращается в качестве параметра в scope.callback()? Не могу просто сделать это: scope.callback(person); Директива не знает, что такое человек... и не должна... точно так же, как ng-change не знает, что такое человек, или, если бы я просто хотел $index ng-repeat..., моя директива должна быть независимой выражения прошло... - person RavenHursT; 21.03.2014
comment
Хорошо .. Я беру свои слова назад .. вы были совершенно правы .. не знаю, как это работает .. но это так .. Спасибо! jsfiddle.net/Troop4Christ/fA4XJ/13 Может быть, вы могли бы объяснить, почему & работает? - person RavenHursT; 21.03.2014