Hussain Hussain - 1 month ago 13
AngularJS Question

File name doesn't get cleared after form.$setPristine for a custom angular directive for file upload

I am using

angular 1.5.8
. After following some resources, I got the file upload working. I had to create a custom directive for that.

Directive

//file-upload-model-directive.js
'use strict';

export default function (app) {

app.directive('fileUploadModel', fileUploadModelDirective);

function fileUploadModelDirective () {
'ngInject';

return {
restrict: 'A',
link: linkFn,
require: 'ngModel'
};

function linkFn (scope, element, attrs, ngModel) {
element.bind('change', function(event){
var files = event.target.files;
var file = files[0];

ngModel.$setViewValue(file);
scope.$apply();
});

}
}
}


I am also using angular's
form
. And I have a "reset" button on this form. I want to clear all the form fields when clicked. And it happens with all form fields except
file
.

View

<form ng-submit="dataCtrl.upload(form)" name="form">
<div class="form-group" ng-class="{'has-error' : form.file.$invalid && !form.file.$pristine}">
<label>Select file</label>
<input type="file" name="file" ng-model="dataCtrl.newUpload.csvFile" file-upload-model required/>
</div>

<div class="form-group" ng-class="{'has-error' : form.comment.$invalid && !form.comment.$pristine}">
<label>Comment</label>
<textarea class="form-control" name="comment"
ng-model="dataCtrl.newUpload.comment" required></textarea>
</div>

<div class="form-group pull-right">
<button type="submit" class="btn btn-success" ng-disabled="form.$invalid">Upload</button>
<button class="btn btn-default" ng-click="dataCtrl.reset(form)" ng-disabled="!form.$dirty">Reset</button>
</div>
</form>


And the Controller

'use strict';

function DataController($log, catalogCnst, requestSV, $http) {
'ngInject';

this.reset = function(form) {
this.newUpload = {};
// form.file.$setViewValue(null); // this didn't work either
form.$setPristine()
};

this.upload = function(form) {
// some code
};
}


When "reset" is clicked, I see that

form.file.$pristine is false
form.file.$invalid is false


But I still see filename near the file upload element.

I also tried adding watch and handling event on the element in the directive

scope.$watch(attrs.fileUploadModel, function(value) {
console.log('attrs.file');
});

element.on('$pristine', function() {
console.log('destroy');
});


But they didn't get invoked.

How do I do this? Please guide me.

Answer

When you clear newUpload, file input does not get cleared. You need to do this separately.

See JSFiddle:

Basically, I added to the directive scope:

scope: {
  model: '=ngModel'
},

... and watch:

scope.$watch('model', function(file) {
  if (!file) {
    element.val('');
  }
});