【问题标题】:AngularJs - Calling controller function from directiveAngularJs - 从指令调用控制器函数
【发布时间】:2017-05-29 09:48:54
【问题描述】:

在 angularjs 项目中,我使用指令通过将文件拖放到 dropzone 中来上传文件。在指令中,我需要调用在我的控制器中定义的函数。

这是我正在做的事情:

(function () {
'use strict';

angular
    .module('app')
    .controller('myController', myController)
    .directive('fileDropzone', function () {
        return {
            restrict: 'A',
            scope: {
                file: '=',
                fileName: '=',
                test: '&callbackFn',
            },
            link: function (scope, element, attrs) {
                var  processDragOverOrEnter;
                processDragOverOrEnter = function (event) {
                    if (event != null) {
                        event.preventDefault();
                    }
                    event.dataTransfer.effectAllowed = 'copy';
                    return false;
                };
                element.bind('dragover', processDragOverOrEnter);
                element.bind('dragenter', processDragOverOrEnter);
                return element.bind('drop', function (event) {
                    var file, reader;
                    if (event != null) {
                        event.preventDefault();
                    }
                    reader = new FileReader();
                    reader.onload = function (evt) {
                        console.log(reader.result);

                        scope.test({});
                    };
                    file = event.dataTransfer.files[0];
                    reader.readAsText(file);
                    return false;
                });
            }
        };
    });

    function myController()
    {
         var vm = this;

         vm.test = function () {
           console.log("It works !");
         };
    }
})();

html 文件:

<div class="container">
    <md-content file-dropzone layout="column" layout-align="center center" class="md-list-item-text" md-whiteframe="1" style="padding:1em;margin:0.5em 0.5em;" flex>
        File drop zone
    </md-content>
</div>

虽然 console.log(reader.result) 指令确实在控制台中显示文件内容,但消息“It works !”没有显示,这意味着函数 test() 永远不会被调用。

我做错了什么?

【问题讨论】:

  • 同时添加 HTML 文件信息..
  • 因为您已经创建了隔离作用域,那么您在任何控制器内部使用指令的地方都会获得它的实例,使用 ctrl 作为链接函数的第四个参数
  • 然后就可以调用控制器的功能了
  • 我们可以将 myController 注册为指令控制器吗?
  • 你错过了在 html 文件的指令元素中添加 callback-fn="vm.test()"

标签: angularjs angularjs-directive


【解决方案1】:

var app = angular.module('exApp', []);

app.controller("Ctrl", function ($scope) {
  $scope.test = function () {
   console.log("Hi you called ctrl function");
  };
  $scope.param = function(name){
  console.log("My name is " + name);
  }
  $scope.testing = function(role){
  console.log("I'm a "+ role);
  }
});

app.directive("testDir", function () {
  return {
    scope: {
      test: "&callFuc",
      param:"&withparam",
      testing:"&"
    },
    template: `<button ng-click="test()">Call Test!
               </button>
               <button ng-click="param({name:'Mani'})">With param!
               </button>
               <button ng-click="clickHere()">Click Me!
               </button>`,
    link:function(scope){
        scope.clickHere = function(){
            scope.testing({msg:"Javascript Developer"});
        };
    }
  };
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<div ng-app="exApp">
  <div ng-controller="Ctrl">
    <div test-dir call-fuc="test()" withparam="param(name)" testing="testing(msg)"></div>
  </div>
</div>

本例无参数;

   scope: {
                file: '=',
                fileName: '=',
                test: '&',
            }
<a ng-click="test()">Call test</a> // in directive

<md-content file-dropzone layout="column" test="vm.test()"
            layout-align="center center" class="md-list-item-text"
            md-whiteframe="1" style="padding:1em;margin:0.5em 0.5em;" 
            flex>
   File drop zone
</md-content>

【讨论】:

  • 经过进一步测试,这是唯一对我有用的解决方案,谢谢。
  • 这个答案需要更多的爱
【解决方案2】:

您可以通过在链接函数中指定第四个变量来访问指令控制器。

更新链接功能:-

link: function (scope, element, attrs, ctrl) {
  console.log(ctrl.test());
}

【讨论】:

  • 请在否决答案之前添加评论。这将有助于未来的答案
  • 我没有否决答案,但它对我不起作用。我有以下错误:“无法读取未定义的属性‘测试’”。如果我尝试在控制台中显示 ctrl 它确实显示“未定义”。
  • @Hal,我问那些反对这个答案的人。可以将 myController 注册为指令控制器吗?
  • 通过向指令对象添加以下键值,我们可以创建指令控制器。返回{控制器:'myController',controllerAs:'ctrl',bindToController:真}; myController 只能被这个指令访问。参考blog.thoughtram.io/angularjs/2015/01/02/…
  • 由于某种原因,在指令中添加定义“控制器”对解决方案的其余部分产生了影响,并且 Angular 无法再将服务注入控制器......我使用了 Manikandan 的解决方案并且它有效。
【解决方案3】:

您需要将 ctrl 作为第四个参数传递给 link 函数。

【讨论】:

    猜你喜欢
    • 2021-04-06
    • 1970-01-01
    • 2018-01-03
    • 1970-01-01
    • 2015-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多