指令attr内部的回调函数定义在不同的attr中

时间:2013-04-09 08:29:56

标签: javascript ajax angularjs angularjs-directive

所以我有这个名为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");
}

当我在my-save指令中console.log() attrs.mySaveCallback时,它只给了我一个字符串callbackFunctionInController(),我读了somewhere我应该$解析它,它会是很好,所以我试着$parse(attrs.mySaveCallback)给了我一些功能,但几乎没有我想要的那个,它让我回来了

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

我做错了什么?这种方法从一开始就有缺陷吗?

7 个答案:

答案 0 :(得分:61)

所以最好的方法是使用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})

答案 1 :(得分:12)

有很多方法可以解决你正在做的事情。你应该知道的第一件事是,一旦DOM元素被模板引擎渲染出来就会调用$http.post(),就是这样。如果你把它放在重复中,那么将对转发器中的每个新项目进行调用,所以我猜这绝对不是你想要的。如果它那么你真的没有正确设计东西,因为仅存在DOM不应该指示对后端的查询。

无论如何,直接回答你的问题;如果您在$ parse上阅读虽然糟糕的文档,它会返回一个评估表达式。通过将范围传递给evaluate on来执行此函数时,将返回您传递的范围上该表达式的当前状态,这意味着您的函数将被执行。

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

是的,一开始有点令人困惑,但你必须明白$ scope会在异步应用程序中不断变化,而这一切都与你想要确定的价值有关,而不仅仅是如何。 $parse对于您希望能够为其分配值的模型的引用更有用,而不仅仅是从中读取。

当然,您可能希望了解如何创建隔离范围或如何$eval()表达式。

$scope.$eval(attrs.mySave);

答案 2 :(得分:9)

您可以使用.$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)
      }
   }
});

道明:Demo

如果要在指令和控制器之间共享数据,可以使用双向绑定

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

答案 3 :(得分: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);
}

并正确打印出条件。

答案 4 :(得分:0)

这对我有用

在视图脚本中

<tag mycallbackattrib="scopemethod">

指令内

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

它被正确调用并且params被传递,但可能不是最好的“有角度的方式”。

答案 5 :(得分:0)

您应该使用ng-click而不是创建自己的指令。

答案 6 :(得分:0)

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