Reputation: 10624
I am attempting to create an AngularJS directive that sends a file name, from an <input type="file">
element, to a file upload factory. The work is based off the following blog post:
http://odetocode.com/blogs/scott/archive/2013/07/05/a-file-input-directive-for-angularjs.aspx
I have my HTML element defined:
<div file-input="file" on-change="readFile()"></div>
With the associated directive set up:
myApp.directive('fileInput', function ($parse)
{
return {
restrict: "A",
template: "<input type='file' />",
replace: true,
link: function (scope, element, attrs) {
var model = $parse(attrs.fileInput);
var onChange = $parse(attrs.onChange);
element.bind('change', function () {
model.assign(scope, element[0].files[0]);
console.log(element[0].files[0]); // correctly references selected file
scope.$apply();
console.log(model(scope)); // correctly references selected file
onChange(scope);
});
}
};
});
When I select a file from the element the change
event is fired and both my console.log
calls print out a reference to the file that I selected. But attempting to print out $scope.file
in my controller does not reflect the file selection:
$scope.file = "nothing";
$scope.readFile = function()
{
$scope.progress = 0;
console.log($scope.file); // print "nothing"
fileReaderFactory.readAsDataUrl($scope.file, $scope)
.then(function (result) {
$scope.imageSrc = result;
});
};
What am I missing that does not allow the controller to properly set and retain the value sent from the directive?
UPDATE
I've made the following updates, but my scope variable is still not being updated. My change function is called, but it doesn't notice any new value given to myModel
.
HTML:
<file-input my-model="fileRef" my-change="readFile()"></file-input>
Directive (input
tag updated to text
for testing purposes):
myApp.directive('fileInput', function ($parse)
{
return {
restrict: "AE",
template: "<input type='text' />",
replace: true,
scope: {
myModel: "=",
myChange: "&"
},
link: function (scope, element, attrs) {
element.bind('change', function () {
scope.myChange();
});
}
};
});
Controller:
$scope.fileRef = "nothing";
$scope.readFile = function()
{
$scope.progress = 0;
console.log($scope.fileRef); // prints "nothing"
fileReaderFactory.readAsDataUrl($scope.fileRef, $scope)
.then(function (result) {
$scope.imageSrc = result;
});
};
Upvotes: 0
Views: 970
Reputation: 1035
try adding file to the link function. I had the same issue and that's what fixed it for me.
As near as I can tell the link acts as the controller (scope) for the template.
However, the one thing that confuses me is that when I added a property to $scope from within a $scope method in the controller the new property is seen by the template. When added outside the $scope method (still in the controller) it is not.
Upvotes: 1
Reputation: 7279
In your directive object add scope: {file-input: '='}
to have two way binding between your directive's scope and it's parent scope.
Upvotes: 1