39

所以我有这个指令叫做 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 指令中时,它只给了我一个 string ,我在某处callbackFunctionInController()读到我应该 $parse 这个,它会很好,所以我尝试了它给了我一些功能,但几乎不是我正在寻找的功能,它还给了我$parse(attrs.mySaveCallback)

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

我究竟做错了什么?这种方法从一开始就存在缺陷吗?

4

7 回答 7

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})
于 2013-04-09T09:17:08.720 回答
12

有很多方法可以去做你正在做的事情。您应该知道的第一件事是,$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

是的,一开始有点令人困惑,但您必须了解 $scope 在异步应用程序中不断变化,这完全取决于您希望何时确定该值,而不仅仅是如何确定。$parse对于引用您希望能够为其分配值的模型更有用,而不仅仅是从中读取。

当然,您可能想阅读有关创建隔离作用域或如何创建$eval()表达式的信息。

$scope.$eval(attrs.mySave);
于 2013-04-09T08:41:45.490 回答
10

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

演示:小提琴

于 2013-04-09T08:38:44.437 回答
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);
}

它会正确打印出条件。

于 2013-10-11T08:37:52.457 回答
0

这对我有用

视图脚本内部

<tag mycallbackattrib="scopemethod">

指令内

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

它被正确调用并传递了参数,但可能不是最好的“角度方式”工作。

于 2013-09-25T10:11:43.610 回答
0

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

于 2014-12-10T05:32:57.993 回答
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);
       });
     }
   };
});
于 2016-12-21T15:10:34.823 回答