Frage

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)};
War es hilfreich?

Lösung

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>

Andere Tipps

You can pass through an object to the scope of the directive using = within the directive to do two way data binding. This way you can make updates to the data within the directive on the object and it will be reflected in it's original location in the controller. In the controller you can then use $scope.watch to see when the data is changed by the directive.

Something like

http://plnkr.co/edit/gQeGzkedu5kObsmFISoH

// Code goes here

angular.module("myApp",[]).controller("MyCtrl", function($scope){
  $scope.something = {value:"some string"}
}).directive("simpleDirective", function(){
  return {
    restrict:"E",
    scope:{someData:"="},
    template:"<button ng-click='changeData()'>this is something different</button>",
    link: function(scope, iElem, iAttrs){
      scope.changeData=function(){
        scope.someData.value = "something else";
      }
    }
  }
});
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top