2

I want to implement a scenario using angularjs in which user select a directory and after selection need to do some processing of each files in that directory.

Please find below code for the same HTML file:

<div ng-app="myApp" ng-controller="myCtrl">
  <input id="folder" type="file" onchange="angular.element(this).scope().checkFiles(this.files)" webkitdirectory="" directory="" multiple="" />
</div>

Javascript code

var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {

  $scope.checkFiles = function(files) {
    console.log(files);

    //add below line of code to trigger onchange event if user select same directory
    angular.element(document.querySelector('#folder'))[0].value = null;
  };
});

Plunker link https://plnkr.co/edit/lDhoShIVgCXLd33mPtbh?p=preview

The written code work for when selected directory has some file in it. But when I select empty directory it does triggers onchange event.

I tried alot but didn't got the root cause for this behavior.

One thing I noticed is that when i remove below line of code

    //add below line of code to trigger onchange event if user select same directory
    angular.element(document.querySelector('#folder'))[0].value = null;

and select a directory with some files and then select a empty directoy onchange event is getting triggred. But onchange event is not triggered if I directly select empty directory on first try.

Need to know why onchange event is not getting triggered for empty directory.

Note: Please try this code on chrome browser not supported for other browsers

raoul.nair
  • 389
  • 1
  • 8
  • 21
  • Angular or not, you can't select a directory. But you may select one or more files, and then a change event will be fired by the file input. – Igwe Kalu Feb 28 '16 at 13:00
  • Possible duplicate of [Directory Chooser in HTML page](http://stackoverflow.com/questions/2809688/directory-chooser-in-html-page) – Igwe Kalu Feb 28 '16 at 13:02
  • @IgweKalu I want to select directory and i am able to do that please check plunker link https://plnkr.co/edit/lDhoShIVgCXLd33mPtbh?p=preview just want to know why onchange event is getting fired on selecting empty directory. – raoul.nair Feb 28 '16 at 13:12
  • each time I select a directory and click choose, it only simply opens the directory to show its contents. After that only cancel options is enabled, unless you select a file or directory (in which case it will simply open the directory again). I don't know how you were able to do so. I wish I could help you... – Igwe Kalu Feb 28 '16 at 13:47
  • Moreover, note that a change event will not be fired unless there is really a change. For instance, if you selected file, a.text, previously and then later select it again, a change event will not be fired. A change would be fired if and only if the current selection is different from the previous. – Igwe Kalu Feb 28 '16 at 13:51
  • @IgweKalu this code will work only on chrome browser and i am logging directory file details on console. I think you are using some other browser – raoul.nair Feb 28 '16 at 13:55
  • So would you consider a solution that only works in Chrome as an actual solution? – Igwe Kalu Feb 28 '16 at 15:24
  • Yes currently I only to implement for chrome – raoul.nair Feb 28 '16 at 15:30

3 Answers3

1

File input is geared towards selecting files. When you select a directory (in Chrome), it's equivalent to selecting all files in the file-tree (i.e. including files of directories inside the selected directory).

So if you selected an empty directory, it amounts to no file selection - and as such, no point in a change event being fired.

Igwe Kalu
  • 14,286
  • 2
  • 29
  • 39
  • but if you comment line 9 code in plunker angular.element(document.querySelector('#folder'))[0].value = null; and 1st select a non empty directory and then select an empty directory onchnge event gets triggered. – raoul.nair Feb 28 '16 at 17:44
  • I see. I wish I have more to offer. I could delete this answer if it's not helpful at all. – Igwe Kalu Mar 01 '16 at 01:50
0

This doesn't look very "Angular". The Angular way would be to do DOM manipulation in a directive, and not in your controller. So you could try a file browser directive like in this jsfiddle. Ideally for your on-change directive, you would assign it a function, like on-change="doSomething()", and then in your controller, you can add logic for this function. See this post for an additional example.

See this cheat sheet on doing things the Angular way.

HTML:

<div ng-controller="parentController">
    <p><a ng-click="load('one.tpl')">One</a> | <a ng-click="load('two.tpl')">Two</a></p>
    <hr>
    <div ng-include="tpl"></div>
</div>

<script type="text/ng-template" id="one.tpl">
    <p>Template One</p>
    <div file-browser>
        <input type="file" name="upload-file">
    </div>
</script>

JS:

angular.module('testapp').controller('parentController', function($scope) {
    $scope.load = function(tpl) {
        $scope.tpl = tpl;
    };
    $scope.load('one.tpl');
});
angular.module('testapp').directive('fileBrowser', function() {
    return {
        restrict: 'A',
        replace: true,
        transclude: true,
        scope: false,
        template:
            '<div class="input-prepend extended-date-picker">'+
                '<input type="button" class="btn" value="browse...">'+
                '<input type="text" readonly class="override">'+
                '<div class="proxied-field-wrap" ng-transclude></div>'+
            '</div>',
        link: function($scope, $element, $attrs, $controller) {
            var button, fileField, proxy;
            fileField = $element.find('[type="file"]').on('change', function() {
                proxy.val(angular.element(this).val());
            });
            proxy = $element.find('[type="text"]').on('click', function() {
                fileField.trigger('click');
            });
            button = $element.find('[type="button"]').on('click', function() {
                fileField.trigger('click');
            });
        }
    };
});
LJ.Wizard
  • 605
  • 1
  • 6
  • 10
0

Chrome initializes FileList object with an empty folder that the reason on change event is not getting triggered. I raised an issue in chromium https://bugs.chromium.org/p/chromium/issues/detail?id=590715 and it was merged to existing issue https://bugs.chromium.org/p/chromium/issues/detail?id=590715

raoul.nair
  • 389
  • 1
  • 8
  • 21