Подтвердить что ты не робот

Функция обратного вызова внутри директивы attr, определенной в разных attr

Итак, у меня есть эта директива, называемая say, mySave, это в значительной степени именно это

app.directive('mySave', function($http) {
   return function(scope, element, attrs) {
      element.bind("click", function() {
          $http.post('/save', scope.data).success(returnedData) {
              // callback defined on my utils service here

              // user defined callback here, from my-save-callback perhaps?
          }
      });
   }
});

сам элемент выглядит следующим образом:

<button my-save my-save-callback="callbackFunctionInController()">save</button>

callbackFunctionInController на данный момент просто

$scope.callbackFunctionInController = function() {
    alert("callback");
}

когда я console.log() attrs.mySaveCallback внутри директивы my-save, он просто дает мне строку callbackFunctionInController(), я читаю где-нибудь, что Я должен проанализировать это, и все будет хорошо, поэтому я попытался $parse(attrs.mySaveCallback), который вернул мне какую-то функцию, но вряд ли тот, который я искал, вернул мне

function (a,b){return m(a,b)} 

Что я делаю неправильно? Этот подход ошибочен с самого начала?

4b9b3361

Ответ 1

Итак, лучший способ - использовать изолированную область видимости, предложенную ProLoser

app.directive('mySave', function($http) {
   return {
      scope: {
        callback: '&mySaveCallback'
      }
      link: function(scope, element, attrs) {
        element.on("click", function() {
            $http.post('/save', scope.$parent.data).success(returnedData) {
                // callback defined on my utils service here

                scope.callback(); // fires alert
            }
        });
      }
   }
});

Для передачи параметров обратно на контроллер выполните это

[11:28] <revolunet> you have to send named parameters 
[11:28] <revolunet> eg my-attr="callback(a, b)" 
[11:29] <revolunet> in the directive: scope.callback({a:xxx, b:yyy})

Ответ 2

Существует много способов сделать то, что вы делаете. Первое, что вы должны знать, это то, что $http.post() будет вызываться, как только этот элемент DOM будет выдан механизмом шаблона и что он. Если вы поместите его внутри повтора, вызов будет выполнен для каждого нового элемента в ретрансляторе, поэтому я предполагаю, что это определенно не то, что вы хотите. И если он , вы действительно неправильно разрабатываете вещи, потому что существование DOM самостоятельно не должно диктовать запросы к серверу.

В любом случае, прямо отвечая на ваш вопрос; если вы читаете хотя бы дрянные документы в $parse, он возвращает вам оценочное выражение. Когда вы выполняете эту функцию, передавая область для оценки, текущее состояние этого выражения в пройденной области будет возвращено, это означает, что ваша функция будет выполнена.

var expression = $parse(attrs.mySave);
results = expression($scope); // call on demand when needed
expression.assign($scope, 'newValu'); // the major reason to leverage $parse, setting vals

Да, сначала это немного запутывает, но вы должны понимать, что переменная $изменяется постоянно в асинхронных приложениях, и все это о КОГДА вам нужно определить значение, а не только как. $parse более полезен для ссылки на модель, для которой вы хотите присвоить значение, а не просто читать.

Конечно, вы можете прочитать о создании области изоляции или о том, как $eval() выражение.

$scope.$eval(attrs.mySave);

Ответ 3

Вы можете использовать . $eval для выполнения оператора в данной области

app.directive('mySave', function($http) {
   return function(scope, element, attrs) {
      $http.post('/save', scope.data).success(returnedData) {
          // callback defined on my utils service here

          // user defined callback here, from my-save-callback perhaps?
          scope.$eval(attrs.mySaveCallback)
      }
   }
});

TD: Демо

Если вы хотите обмениваться данными между директивой и контроллером, вы можете использовать двустороннюю привязку

app.controller('AppController', function ($scope) {
   $scope.callbackFunctionInController = function() {
      console.log('do something')
   };

   $scope.$watch('somedata', function(data) {
      console.log('controller', data);
   }, true);
});

app.directive('mySave', function($http, $parse) {
   return {
     scope: {
       data: '=mySaveData',
       callback: '&mySaveCallback' //the callback
     },
     link: function(scope, element, attrs) {
       $http.get('data.json').success(function(data) {
         console.log('data', data);
         scope.data = data;
         scope.callback(); //calling callback, this may not be required
       });
     }
   };
});

Демо: Fiddle

Ответ 4

scope: {
    callback: '&mySaveCallback'
}

Явная установка области явно может быть хорошим решением, но если вы хотите, чтобы другие части исходной области не были доступны, вы не можете, потому что вы просто перезаписали ее. По какой-то причине мне также нужно было достичь других частей области, поэтому я использовал ту же реализацию, что и ng-click.

Использование моей директивы в HTML:

<div my-data-table my-source="dataSource" refresh="refresh(data)">

Внутри директивы (без явной настройки области):

var refreshHandler = $parse(attrs.refresh);
    scope.$apply(function () {
    refreshHandler( {data : conditions}, scope, { $event: event });
});

С этим я могу вызвать функцию в контроллере и передать ей параметры.

В контроллере:

$scope.refresh= function(data){
    console.log(data);
}

И он корректно печатает условия.

Ответ 5

Это сработало для меня

Внутри представления script

<tag mycallbackattrib="scopemethod">

Внутри директивы

$scope[attrs.mycallbackattrib](params....);

Он правильно вызывается и передаются параметры, но, возможно, это не лучший способ angular.

Ответ 6

Вы должны использовать ng-click вместо создания своей собственной директивы.

Ответ 7

app.directive('mySave', function($http, $parse) {
   return {
     scope: {
       data: '=mySaveData',
       callback: '&' //the callback
     },
     link: function(scope, element, attrs) {
       $http.get('data.json').success(function(data) {
         console.log('data', data);
         if (scope.callback()) scope.callback().apply(data);
       });
     }
   };
});