2

In an angularjs project I am using a directive to upload files by drag/dropping them in a dropzone. In the directive I need to call a function that is defined within my controller.

Here is what I am doing:

(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 file:

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

While the console.log(reader.result) instruction does display the file content in the console, the message "It works !" is not shown, which means the function test() is never called.

What am I doing wrong ?

8
  • 2
    Add HTML file info also.. Commented May 29, 2017 at 9:52
  • 1
    as you have created isolated scope then where you are using directive inside of any controller there you will get instance of it use ctrl as fourth parameter of link function Commented May 29, 2017 at 9:53
  • then you can call function of controller Commented May 29, 2017 at 9:53
  • Can we register myController as directive controller? Commented May 29, 2017 at 9:59
  • 3
    you have missed to add callback-fn="vm.test()" in directive element at html file Commented May 29, 2017 at 10:18

3 Answers 3

18

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>

This example is without parameter;

   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>
Sign up to request clarification or add additional context in comments.

2 Comments

After further testing this is the only solution that worked for me, thanks.
This answer needs more love
-1

You can access the directive controller by specifying the fourth variable in link function.

Updated Link function:-

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

6 Comments

Please add comment before downvoting an answer. It will be helpful in future answers
I have not downvoted the answer, but it does not work for me. I have the following error: "Cannot read property 'test' of undefined". If I try to display ctrl in the console it indeed shows "undefined".
@Hal, I was asking to those person who were downvoting this answer. Can you register myController as directive controller?
By adding following key-value to directive object, we can create directive controller. return { controller: 'myController', controllerAs: 'ctrl', bindToController: true }; myController will only be accessible to this directive only. Refer blog.thoughtram.io/angularjs/2015/01/02/…
For some reason, adding the definition "controller" in the directive had impact on the rest of the solution and angular could not inject services into controllers anymore... I used Manikandan's solution and it worked.
|
-2

You need to pass ctrl as fourth parameter inside link function.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.