Reputation: 70416
HTML:
<form name="form">
<input type="file" ng-model="document" valid-file required>
<input type="submit" value="{{ !form.$valid && 'invalid' || 'valid' }}">
</form>
Custom directive to listen for input[type=file] changes:
myApp.directive('validFile',function(){
return {
require:'ngModel',
link:function(scope,el,attrs,ngModel){
//change event is fired when file is selected
el.bind('change',function(){
scope.$apply(function(){
ngModel.$setViewValue(el.val());
ngModel.$render();
});
});
}
};
});
When file is selected following error appears in console:
Error: InvalidStateError: DOM Exception 11 Error: An attempt was made to use an object that is not, or is no longer, usable.
Try with plunkr: http://plnkr.co/edit/C5j5e0JyMjt9vUopLDHc?p=preview
Without the directive the the state of the input file field wont be pushed to form.$valid. Any ideas why I get this error and how to fix this?
Upvotes: 24
Views: 25544
Reputation: 6075
After updating to AngularJS 1.2.x the snippet looks not working properly anymore and the file input doesn't sticks with the selected file value, making the form unusable.
Changing the directive back to your original one, and removing the ngModel.$render()
it looks working like a charm:
.directive('validFile', function () {
return {
restrict: 'A',
require: '?ngModel',
link: function (scope, el, attrs, ngModel) {
el.bind('change', function () {
scope.$apply(function () {
ngModel.$setViewValue(el.val());
});
});
}
};
Upvotes: 4
Reputation: 54524
From the reference of NgModelController.$render()
Called when the view needs to be updated. It is expected that the user of the ng-model directive will implement this method.
You need to implement $render() to call it. You can do something like this
myApp.directive('validFile', function () {
return {
require: 'ngModel',
link: function (scope, el, attrs, ngModel) {
ngModel.$render = function () {
ngModel.$setViewValue(el.val());
};
el.bind('change', function () {
scope.$apply(function () {
ngModel.$render();
});
});
}
};
});
Upvotes: 29