Search code examples
angularjsangularjs-directiveangularjs-controlleruploadcare

How to pass async data from directive to controller?


I want to compile a third-party api (uploadcare) to a directive.

The api will return the data info after uploaded in async then I want to do something with the return data in my controller but I have to idea how to pass the return data from directive to controller. Below is my code.

in js

        link: function (scope, element, attrs) {
            //var fileEl  = document.getElementById('testing');
            var a = function() {

                var file    = uploadcare.fileFrom('event', {target: fileEl});
                file.done(function(fileInfo) {

                    //scope.$apply(attrs.directUpload)
                   //HERE IS MY PROBLEM.
                   //How can I get the fileInfo then pass and run it at attrs.directUpload

                }).fail(function(error, fileInfo) {

                }).progress(function(uploadInfo) {
                  //Show progress bar then update to node
                  console.log(uploadInfo);
                });
            };

            element.bind('change', function() {a()});
        }

in html

<input type="file" direct-upload="doSomething()">

in controller

$scope.doSomething = function() {alert(fileInfo)};

Solution

  • AngularJS allows to execute expression in $parent context with specified values, in your case doSomething().

    Here's what you need to do that:

    1. In directive definition, mark directUpload as expression:
    scope: {
        directUpload: "&"
    }
    
    1. In done callback, call:
    scope.directUpload({fileInfo: fileInfo})
    
    1. Update markup:
    <input type="file" direct-upload="doSomething(fileInfo)">
    

    To summorize: scope.directUpload is now a callback, which executes expression inside attribute with specifeid values. This way you can pass anything into controller's doSomething.

    Read $compile docs for detailed explanation and examples.

    Example you might find useful:

    angular
    .module("app", [])
    .directive("onDone", function ($timeout) {
      function link (scope, el, attr) {
        $timeout(function () {
          scope.onDone({
            value: "something"
          });
        }, 3000)
      }
      return {
        link: link,
        scope: {
          onDone: "&"
        }
      }
    })
    .controller("ctrl", function ($scope) {
      $scope.doneValue = "nothing";
      $scope.done = function (value) {
        $scope.doneValue = value;
      };
    })
    
    <body ng-controller="ctrl">
      Waiting 3000ms
      <br>
    <div on-done="done(value)">
      Done: {{doneValue}}
    </div>
    </body>