Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pass arguments to parent controller method from directive

How do I pass on arguments to the end() method of the controller from the directive?

Directive

var fileuploader = function () {
    return {
        restrict: 'E',
        scope: {
            onEnd: '&',
        },
        controller: function ($scope) {
            // When upload is done
            $scope.onEnd(/* file */);
        }
    };
}

Controller

module.controller('Ctrl', function ($scope) {
    $scope.end = function (file) {
        console.log('file', file);
    };
});

Template:

<div ng-controller='Ctrl'>
    <fileuploader on-end='end()'></fileuploader>
</div>

I also wonder if this is the angular way of doing things because I don't see this used anywhere else. Maybe the following is more angular?

Directive

var fileuploader = function () {
    return {
        restrict: 'E',
        scope: {
            onEnd: '=',
        },
        controller: function ($scope) {
            // When upload is done
            $scope.file = file;
        }
    };
}

Controller

module.controller('Ctrl', function ($scope) {
    $scope.$watch('file', function (val) {
        console.log('file', val);
    });
});

Template

<div ng-controller='Ctrl'>
    <fileuploader on-end='file'></fileuploader>
</div>

This adds some indirection though and is maybe less forward then calling a controller method.

like image 669
Pickels Avatar asked Jul 01 '13 12:07

Pickels


1 Answers

Aight sir, here is an example, apologizes if my explanation isn't super clear: http://plnkr.co/edit/3wO3So

View:

   <div ng-controller='fooCtrl'>
        <fileuploader directive-end-fn='end(directiveData)'></fileuploader>
    </div>

Controller & Directive

app.controller('fooCtrl', function($scope) {
   /// This end() function sits on the controller it will be passed data from the directive
   $scope.end = function (directiveData) {
        console.log("I'm in the controller " + directiveData);
  };
});

app.directive('fileuploader', function(){
  return {
    restrict: 'E',
    replace: true,
    scope: {
       /// I bind the end function from the controller to scope.directiveEndFn, 
       //I'll use it in the link function later
      directiveEndFn: '&',
    },
    /// I take your directive, add an input box as a model (model.input)
    template: '<div><input type="text" ng-model="model.input"><div>{{model.input}}</div></div>',
    /// Put your logic in the linking function, so it runs all the time.     
    link: function(scope,element){
        /// This could be any event, right now I'm watching the model.input for event changes. 
        //It fires a callback that allows me to do stuff when changes happen
        scope.$watch("model.input", function(myModelValue){
              // I use scope.directiveEndFn with an "Object Map", 
              // I tell it to use the model.input which is now assigned to myModelValue value, 
              // It's a $watch convention you can read more about, whatever gets "Watched" is
              // is the parameter of the callback.
              // The object map links myModelValue to DirectiveData
              // Look at the view, which passes this information,
              // from the directive to the controller - directive-end-fn='end(directiveData)'
              scope.directiveEndFn({directiveData: myModelValue});
        });
    }
  }
});

This is a really good explanation on how to do this also. There are a couple more techniques there too!

Also if you want to understand scope interpolation, using the &, view this.

like image 105
Nicholas Dynan Avatar answered Oct 05 '22 23:10

Nicholas Dynan