New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support input[type=file] binding #1375

Closed
guruward opened this Issue Sep 18, 2012 · 145 comments

Comments

Projects
None yet
@guruward
Copy link

guruward commented Sep 18, 2012

hi trying to do a simple file upload :) but the input of type=file dont seem to bind ive tried hg-model-instant but get nothing, even upgraded to 1.0.2 and nothing

@coli

This comment has been minimized.

Copy link

coli commented Sep 18, 2012

There is no default binding provided by angular to input type=file.

But then, file input is real-only to javascript, the only benefit such a binding could help is on clearing the fileinput. (Angular also doesn't provide framework support to ajax upload of file right now I believe)

@lgersman

This comment has been minimized.

Copy link

lgersman commented Sep 28, 2012

@coli : thats not the whole truth.

It would make sense to be able to catch the onchange event on input[file].

At https://github.com/lgersman/jquery.orangevolt-ampere we have exactly that scenario : file uploads via XMLHTTPRequest V2.
Therefore we implemented our own directive to catch input[file] change events to get fileuploads done without page reloading.

I would love to see that feature in angularjs !

@jgoldber

This comment has been minimized.

Copy link

jgoldber commented Mar 2, 2013

Has there been any progress made with binding to an input of type file? I have been searching for a solution and can't seem to find one that works...

@guruward

This comment has been minimized.

Copy link

guruward commented Mar 2, 2013

my solution was just Ajax instead of request or http.post

Sent from my iPad

On Mar 1, 2013, at 7:16 PM, "jgoldber" <notifications@github.commailto:notifications@github.com> wrote:

Has there been any progress made with binding to an input of type file? I have been searching for a solution and can't seem to find one.


Reply to this email directly or view it on GitHubhttps://github.com//issues/1375#issuecomment-14321221.

@jgoldber

This comment has been minimized.

Copy link

jgoldber commented Mar 2, 2013

Best solution I found: http://jsfiddle.net/marcenuc/ADukg/49/. Please share if you come across a better solution.

@Siyfion

This comment has been minimized.

Copy link

Siyfion commented Mar 13, 2013

Yeah, this really needs looking at; being able to select & upload a file is fairly crucial to most web applications, so supporting this input is a pretty obvious missing feature.

@andrewrk

This comment has been minimized.

Copy link

andrewrk commented Mar 20, 2013

Bump. This needs to be added to a milestone.

@ManiacalAce

This comment has been minimized.

Copy link

ManiacalAce commented Mar 24, 2013

Another shout out in support of this.

@glebm

This comment has been minimized.

Copy link

glebm commented Mar 29, 2013

ng-model file could set value to a file from HTML5 File API, there are Flash and Silverlight polyfills for IE8/IE9

@coli

This comment has been minimized.

Copy link

coli commented Mar 29, 2013

Yeah, either set the value to the file or to the input element (containing reference to the file)

@bjconlan

This comment has been minimized.

Copy link

bjconlan commented Mar 31, 2013

This solution depends on filereader being implemented:

...
.directive('file', function() {
    return {
        restrict: 'E',
        template: '<input type="file" />',
        replace: true,
        require: 'ngModel',
        link: function(scope, element, attr, ctrl) {
            var listener = function() {
                scope.$apply(function() {
                    attr.multiple ? ctrl.$setViewValue(element[0].files) : ctrl.$setViewValue(element[0].files[0]);
                });
            }
            element.bind('change', listener);
        }
    }
});
<file name="image" ng-model="inputFile" accept="image/png,image/jpg,image/jpeg" />

You then have to do some xhr stuff yourself but I believe that this is outside the gui binding and more processing logic.

and if you lack imagination:

var file = $scope.inputFile;
$http.put('http://localhost:5984/demo/d06917e8d1fae1ae162ea7773c003f0b/' + file.name + '?rev=4-c10029f35a5c5ed9bd8cc31bf8589d3c', file, { headers: { 'Content-Type' : file.type } });

This works because of xhr2 (http://www.html5rocks.com/en/tutorials/file/xhr2) and please excuse the long example upload url, its a couchdb document endpoint (attachment).

@glebm

This comment has been minimized.

Copy link

glebm commented Mar 31, 2013

It is possible to make this work in IE8/9 by combining this flash-based FileReader Polyfill https://github.com/Jahdrien/FileReader and this pure js FormData polyfill that relies on FileReader https://github.com/francois2metz/html5-formdata. update Moxie is a better polyfill

@jvanalst

This comment has been minimized.

Copy link

jvanalst commented Apr 19, 2013

My solution was pretty sketchy, at least as sketchy as the jsfiddle above where the controller prototype is diddled with...

In the controller:

    $scope.updateImage = '(' + function () {
      alert('moo');
    }.toString() + ')();';

Stringify my desired onchange callback and wrap it in a closure.

   <input type="file" name="image" onchange="{{updateImage}}" ng-model="image">

Insert it into the DOM using Angular

Not exactly pretty but it works in Webkit. I didn't do any cross browser testing.

@programmist

This comment has been minimized.

Copy link

programmist commented May 1, 2013

I'm on 1.0.5 and it's still broken. We used Jgoldber's example and tweaked it a bit:
http://jsfiddle.net/ADukg/2589/

This example will only work for one controller, so if you have multiple controllers, each with file inputs you'll need to make some changes.

Haven't tested it on IE yet, but my guess (knowing IE) is that it won't work.

@neilsarkar

This comment has been minimized.

Copy link

neilsarkar commented Jul 18, 2013

Assuming that you just want to call a function in your scope that takes the input element as an argument, this is pretty straightforward to implement in a directive:

http://jsfiddle.net/neilsarkar/vQzKJ/

(modified from the above jsfiddle, thanks @programmist)

@cztomsik

This comment has been minimized.

Copy link

cztomsik commented Aug 1, 2013

'use strict';

function filesModelDirective(){
  return {
    controller: function($parse, $element, $attrs, $scope){
      var exp = $parse($attrs.filesModel);

      $element.on('change', function(){
        exp.assign($scope, this.files);
        $scope.$apply();
      });
    }
  };
}

configuration:

angular.module(...).directive('filesModel', filesModelDirective)

usage:

<input type="file" files-model="someObject.files" multiple>
@mbana

This comment has been minimized.

Copy link

mbana commented Aug 14, 2013

Please do fix this soon.

@ntrp

This comment has been minimized.

Copy link

ntrp commented Aug 14, 2013

Still having problems.. in some versions it works but is anyway not supported

@cztomsik

This comment has been minimized.

Copy link

cztomsik commented Aug 27, 2013

Since 1.5.0 $digest has to be called if you're using onchange workaround:

<input type="file" onchange="angular.element(this).scope().myController.uploadFile(this.files[0]); angular.element(this).scope().$digest();">
@tb01923

This comment has been minimized.

Copy link

tb01923 commented Aug 29, 2013

+1 for better support on the ng-change and the input/file. Use case: as an uploader of an image, I would like to be able to edit that image (resize and crop) prior to uploading for optimal display. Implementation: browse to image (using input/file) and on the onchange event move the file to the canvas and edit with fabricjs. I can;t think of a non-on change implementation.

cztomsik - I am on 1.0.7 and I cannot get your solution to work - the scope(this) function resolves fine, but the controller cannot be found, uploadFile function is listed as a member of the scope(this).

Messing about, I have a slight modification on the technique, which seems to be working for me (i still don't know why I had the :

< input type="file" name="file" ng-model="file" onchange="invokeUploadFile(this)"/ >

var invokeUploadFile = function(that) {
angular.element(that).scope().uploadFile(that)
angular.element(that).scope().$digest();
}

@cztomsik

This comment has been minimized.

Copy link

cztomsik commented Aug 30, 2013

Could you provide jsfiddle/plunker?
Thx

    1. 2013 v 18:17, tb01923 notifications@github.com:

+1 for better support on the ng-change and the input/file. Use case: as an uploader of an image, I would like to be able to edit that image (resize and crop) prior to uploading for optimal display. Implementation: browse to image (using input/file) and on the onchange event move the file to the canvas and edit with fabricjs. I can;t think of a non-on change implementation.

cztomsik - I am on 1.0.7 and I cannot get your solution to work - the scope(this) function resolves fine, but the controller cannot be found, uploadFile function is listed as a member of the scope(this) object but when I remove the controller I get

Uncaught ReferenceError: uploadFile is not defined blah.js:15
$scope.uploadFile blah.js:15
invokeScope blah.js:4
onchange


Reply to this email directly or view it on GitHub.

@blaise-io

This comment has been minimized.

Copy link
Contributor

blaise-io commented Oct 23, 2013

+1. Need it for initiating an HTML5 file upload when a user picks a file. It's easy to work around, but I'd expect this to work.

@edwardrf

This comment has been minimized.

Copy link

edwardrf commented Nov 11, 2013

+1. please implement, not implementing it is totally not intuitive.

@noducks

This comment has been minimized.

Copy link

noducks commented Nov 15, 2013

+1

@gjlaubenstein

This comment has been minimized.

Copy link

gjlaubenstein commented Sep 8, 2015

+1

1 similar comment
@mattdisipio

This comment has been minimized.

Copy link

mattdisipio commented Sep 23, 2015

+1

@dciccale

This comment has been minimized.

Copy link

dciccale commented Sep 26, 2015

this worked for me, may help

angular.module('app', [])
  .controller('MainCtrl', MainCtrl)
  .directive('fileChange', fileChange);

  function MainCtrl($scope) {
    $scope.upload = function () {
      // do something with the file
      alert($scope.file.name);
    };
  }

  function fileChange() {
    return {
      restrict: 'A',
      require: 'ngModel',
      scope: {
        fileChange: '&'
      },
      link: function link(scope, element, attrs, ctrl) {
        element.on('change', onChange);

        scope.$on('destroy', function () {
          element.off('change', onChange);
        });

        function onChange() {
          ctrl.$setViewValue(element[0].files[0]);
          scope.fileChange();
        }
      }
    };
  }
<div ng-app="app" ng-controller="MainCtrl">
  <input type="file" file-change="upload()" ng-model="file">
</div>

http://plnkr.co/edit/JYX3Pcq18gH3ol5XSizw?p=preview

@grzhan

This comment has been minimized.

Copy link

grzhan commented Oct 1, 2015

+1

3 similar comments
@wal0x

This comment has been minimized.

Copy link

wal0x commented Oct 6, 2015

+1

@xujun1986

This comment has been minimized.

Copy link

xujun1986 commented Oct 29, 2015

+1

@ghadeer-io

This comment has been minimized.

Copy link

ghadeer-io commented Nov 2, 2015

+1

@shakhrillo

This comment has been minimized.

Copy link

shakhrillo commented Nov 3, 2015

+1000000000000000000000000

@jsanchezs

This comment has been minimized.

Copy link

jsanchezs commented Nov 5, 2015

+1

1 similar comment
@w00t3n4t0r

This comment has been minimized.

Copy link

w00t3n4t0r commented Nov 18, 2015

+1

@santhosh77h

This comment has been minimized.

Copy link

santhosh77h commented Nov 18, 2015

@dciccale can you please provide plunker example.

@dciccale

This comment has been minimized.

@lovasoa

This comment has been minimized.

Copy link

lovasoa commented Feb 21, 2016

+1

1 similar comment
@renanleme

This comment has been minimized.

Copy link

renanleme commented Mar 16, 2016

+1

@westonganger

This comment has been minimized.

Copy link

westonganger commented Mar 28, 2016

+1 There should be a directive built into the core library for this. Its pretty ridiculous

@robinswaylu

This comment has been minimized.

Copy link

robinswaylu commented Apr 8, 2016

+1

@bogomips

This comment has been minimized.

Copy link

bogomips commented Apr 18, 2016

+1
is the feature scheduled for one of the next releases?

@MadJlzz

This comment has been minimized.

Copy link

MadJlzz commented Apr 29, 2016

+1

1 similar comment
@nadeemkhan

This comment has been minimized.

Copy link

nadeemkhan commented Jul 15, 2016

+1

@matt-catellier

This comment has been minimized.

Copy link

matt-catellier commented Jul 20, 2016

How to this in projects where $scope is never being injected into the controller. I am using laravel angular which uses GULP and ES6 way of declaring controllers.

i.e.

class TestController{
    constructor(API){
        'ngInject';
        this.API = API
    }

    $onInit(){
        this.file = null;
    }
    upload() {
        console.log(this.file)
    }
    fileChanged(elm) {
        console.log('hey')
        this.file = elm.file;
        this.$apply();
    }
}

export const TestComponent = {
    templateUrl: './views/app/components/test/test.component.html',
    controller: TestController,
    controllerAs: 'vm',
    bindings: {}
}

I found a work around I believe. http://stackoverflow.com/questions/38449126/how-to-set-up-ng-file-upload-in-laravel-angular-project/38486379#38486379

@flexchar

This comment has been minimized.

Copy link

flexchar commented Aug 8, 2016

+1

@NabinKhatiwada

This comment has been minimized.

Copy link

NabinKhatiwada commented Apr 13, 2017

@ntrp @guruward @coli @lgersman @jgoldber @Siyfion
How did you fix validtion for
My Validation:
this.catalougeForm = this.catalougeFormBuilder.group({
catalougeIconName: ['',Validators.required]
});
Html:
<input type="file" accept="image/*" class="form-control" formControlName="catalougeIconName"
(change)="changeListener($event)">

My validator is considering catalougeIconName value as empty/null after i upload.
Image is being sent ,but validator is not working

@neha-s16

This comment has been minimized.

Copy link

neha-s16 commented May 10, 2017

Any updates on this?

@zios07

This comment has been minimized.

Copy link

zios07 commented Dec 22, 2017

Any updates ?

@petebacondarwin

This comment has been minimized.

Copy link
Member

petebacondarwin commented Dec 22, 2017

@angular angular locked as resolved and limited conversation to collaborators Dec 22, 2017

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.