Skip to content
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
Closed

support input[type=file] binding #1375

guruward opened this issue Sep 18, 2012 · 145 comments

Comments

@guruward
Copy link

@guruward 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
Copy link

@coli 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
Copy link

@lgersman 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
Copy link

@jgoldber 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
Copy link
Author

@guruward 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" <[email protected]mailto:[email protected]> 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
Copy link

@jgoldber 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
Copy link

@Siyfion 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
Copy link

@andrewrk andrewrk commented Mar 20, 2013

Bump. This needs to be added to a milestone.

@ManiacalAce
Copy link

@ManiacalAce ManiacalAce commented Mar 24, 2013

Another shout out in support of this.

@glebm
Copy link

@glebm 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
Copy link

@coli coli commented Mar 29, 2013

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

@bjconlan
Copy link

@bjconlan 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
Copy link

@glebm 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
Copy link

@jvanalst 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
Copy link

@programmist 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
Copy link

@neilsarkar 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
Copy link

@cztomsik 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
Copy link

@mbana mbana commented Aug 14, 2013

Please do fix this soon.

@ntrp
Copy link

@ntrp ntrp commented Aug 14, 2013

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

@cztomsik
Copy link

@cztomsik 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
Copy link

@tb01923 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
Copy link

@cztomsik cztomsik commented Aug 30, 2013

Could you provide jsfiddle/plunker?
Thx

    1. 2013 v 18:17, tb01923 [email protected]:

+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
Copy link
Contributor

@blaise-io 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
Copy link

@edwardrf edwardrf commented Nov 11, 2013

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

@noducks
Copy link

@noducks noducks commented Nov 15, 2013

+1

@gjlaubenstein
Copy link

@gjlaubenstein gjlaubenstein commented Sep 8, 2015

+1

1 similar comment
@mattdisipio
Copy link

@mattdisipio mattdisipio commented Sep 23, 2015

+1

@dciccale
Copy link

@dciccale 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
Copy link

@grzhan grzhan commented Oct 1, 2015

+1

3 similar comments
@wal0x
Copy link

@wal0x wal0x commented Oct 6, 2015

+1

@xujun1986
Copy link

@xujun1986 xujun1986 commented Oct 29, 2015

+1

@ghadeer-io
Copy link

@ghadeer-io ghadeer-io commented Nov 2, 2015

+1

@shakhrillo
Copy link

@shakhrillo shakhrillo commented Nov 3, 2015

+1000000000000000000000000

@jsanchezs
Copy link

@jsanchezs jsanchezs commented Nov 5, 2015

+1

1 similar comment
@w00t3n4t0r
Copy link

@w00t3n4t0r w00t3n4t0r commented Nov 18, 2015

+1

@santhosh77h
Copy link

@santhosh77h santhosh77h commented Nov 18, 2015

@dciccale can you please provide plunker example.

@lovasoa
Copy link

@lovasoa lovasoa commented Feb 21, 2016

+1

1 similar comment
@renanleme
Copy link

@renanleme renanleme commented Mar 16, 2016

+1

@westonganger
Copy link

@westonganger westonganger commented Mar 28, 2016

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

@robinswaylu
Copy link

@robinswaylu robinswaylu commented Apr 8, 2016

+1

@bogomips
Copy link

@bogomips bogomips commented Apr 18, 2016

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

@MadJlzz
Copy link

@MadJlzz MadJlzz commented Apr 29, 2016

+1

1 similar comment
@nadeemkhan
Copy link

@nadeemkhan nadeemkhan commented Jul 15, 2016

+1

@matt-catellier
Copy link

@matt-catellier 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
Copy link

@flexchar flexchar commented Aug 8, 2016

+1

@NabinKhatiwada
Copy link

@NabinKhatiwada 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
Copy link

@neha-s16 neha-s16 commented May 10, 2017

Any updates on this?

@zios07
Copy link

@zios07 zios07 commented Dec 22, 2017

Any updates ?

@petebacondarwin
Copy link
Member

@petebacondarwin 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.
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
You can’t perform that action at this time.