ng-model for `<input type="file"/>` (with directive DEMO) ng-model for `<input type="file"/>` (with directive DEMO) angularjs angularjs

ng-model for `<input type="file"/>` (with directive DEMO)


I created a workaround with directive:

.directive("fileread", [function () {    return {        scope: {            fileread: "="        },        link: function (scope, element, attributes) {            element.bind("change", function (changeEvent) {                var reader = new FileReader();                reader.onload = function (loadEvent) {                    scope.$apply(function () {                        scope.fileread = loadEvent.target.result;                    });                }                reader.readAsDataURL(changeEvent.target.files[0]);            });        }    }}]);

And the input tag becomes:

<input type="file" fileread="vm.uploadme" />

Or if just the file definition is needed:

.directive("fileread", [function () {    return {        scope: {            fileread: "="        },        link: function (scope, element, attributes) {            element.bind("change", function (changeEvent) {                scope.$apply(function () {                    scope.fileread = changeEvent.target.files[0];                    // or all selected files:                    // scope.fileread = changeEvent.target.files;                });            });        }    }}]);


I use this directive:

angular.module('appFilereader', []).directive('appFilereader', function($q) {    var slice = Array.prototype.slice;    return {        restrict: 'A',        require: '?ngModel',        link: function(scope, element, attrs, ngModel) {                if (!ngModel) return;                ngModel.$render = function() {};                element.bind('change', function(e) {                    var element = e.target;                    $q.all(slice.call(element.files, 0).map(readFile))                        .then(function(values) {                            if (element.multiple) ngModel.$setViewValue(values);                            else ngModel.$setViewValue(values.length ? values[0] : null);                        });                    function readFile(file) {                        var deferred = $q.defer();                        var reader = new FileReader();                        reader.onload = function(e) {                            deferred.resolve(e.target.result);                        };                        reader.onerror = function(e) {                            deferred.reject(e);                        };                        reader.readAsDataURL(file);                        return deferred.promise;                    }                }); //change            } //link    }; //return});

and invoke it like this:

<input type="file" ng-model="editItem._attachments_uri.image" accept="image/*" app-filereader />

The property (editItem.editItem._attachments_uri.image) will be populated with the contents of the file you select as a data-uri (!).

Please do note that this script will not upload anything. It will only populate your model with the contents of your file encoded ad a data-uri (base64).

Check out a working demo here:http://plnkr.co/CMiHKv2BEidM9SShm9Vv


How to enable <input type="file"> to work with ng-model

Working Demo of Directive that Works with ng-model

The core ng-model directive does not work with <input type="file"> out of the box.

This custom directive enables ng-model and has the added benefit of enabling the ng-change, ng-required, and ng-form directives to work with <input type="file">.

angular.module("app",[]);angular.module("app").directive("selectNgFiles", function() {  return {    require: "ngModel",    link: function postLink(scope,elem,attrs,ngModel) {      elem.on("change", function(e) {        var files = elem[0].files;        ngModel.$setViewValue(files);      })    }  }});
<script src="//unpkg.com/angular/angular.js"></script>  <body ng-app="app">    <h1>AngularJS Input `type=file` Demo</h1>        <input type="file" select-ng-files ng-model="fileArray" multiple>    <code><table ng-show="fileArray.length">    <tr><td>Name</td><td>Date</td><td>Size</td><td>Type</td><tr>    <tr ng-repeat="file in fileArray">      <td>{{file.name}}</td>      <td>{{file.lastModified | date  : 'MMMdd,yyyy'}}</td>      <td>{{file.size}}</td>      <td>{{file.type}}</td>    </tr>    </table></code>      </body>