I copied a custom directive that watches for changes on form file inputs.
angular.module('customDirective', [])
.directive('ngFileInputChange', function() {
return {
restrict: 'A',
link: function (scope, element, attrs) {
var onChangeHandler = scope.$eval(attrs.ngFileInputChange);
element.bind('change', onChangeHandler);
}
};
});
Then I use it in the template like so:
<input ng-model="vm.image" ng-file-input-change="vm.base64Test" ...>
And this works fine.
However, this doesn't work:
<input ng-model="vm.image" ng-file-input-change="vm.base64Test()" ...>
Note the ()
at the end of base64Test()
. With a generic ng-click
, the parenthesis are fine, or even required (how else would I pass arguments to the function?) but with the custom directive, parenthesis cause an error.
I only have a vague understanding of what scope.$eval(attrs.ngFileInputChange)
is actually doing, so maybe I could make some change in that?
EDIT:
I should also add that I need access to some scope variables. For example, if I didn't have to use the custom directive, I would write something like this in my controller:
vm.base64Test(associatedData){
console.log(associatedData);
}
And then:
<input ng-change("vm.base64Test(vm.associatedData)">
But ng-change doesn't watch file input contents and the custom directive doesn't allow arguments (other than event), so I'm stuck.
Firstly, if you're planning on calling a method from a directive's API (so to speak), you need to identify it as a callback:
This simply means you're defined/exposing a way to declare a callback when the
scope.onChange
gets triggered. It also means you don't need to$parse
or$eval
since the isolate scope can handle that for you.Next you can trigger that callback much like you're already doing:
One thing to note is that I'm calling the callback within the
$scope.$apply
. Because you're listening on non-angular events (e.g. onChange), you need to notify angular a change has occurred outside of the$digest
cycle.Where you've declared your directive, in your actual callback (probably defined on your view controller) you can pass the payload to the method like so:
When passing a function to a directive you usually need to pass the function pointer, so the directive can call the function later with arbitrary arguments.
In this case, your directive is evaluating the attribute to a function pointer (that's what the $eval is doing), and then binding it as a
change
handler to the element the directive is attached to. You don't need (or want) to have parenthesis.There's nothing wrong with your code as it is currently. I have a directive which does the exact same thing, it works great! (and when your function
vm.base64Test
is called you will get the standard arguments for a change event on an input.) So you can havevm.base64Test
be: