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

IE10 uploading twice, or not at all. #451

Closed
MattWatt opened this issue Dec 12, 2014 · 19 comments
Closed

IE10 uploading twice, or not at all. #451

MattWatt opened this issue Dec 12, 2014 · 19 comments

Comments

@MattWatt
Copy link

Nice library, however I'm encountering some strangeness with IE10.

If I choose the same file after an attempt at uploading, my file model is a blank string. A 3rd attempt and it's an empty array, according to VS.

If I choose a file and it's successfully uploaded, the next time I attempt to a file, it fires my ng-file-change function twice with the same file.

I've looked over the other issues:
#235
#141 (comment)

It appears this was supposed to be corrected recently.

I'm running 2.0.4. Attempting to do a single file at a time upload behavior. Hoping you can take a look. I'm running native IE10 in Standards mode. Behavior works correctly in Chrome.

My HTML

<button type="button" class="button-primary" ng-file-select ng-model="file" ng-file-change="addAttachment(file)" ng-multiple="false">
    Add Attachment
</button>

My Controller's JS Function:

$scope.addAttachment = function addAttachment(file) {

    // Validate File Size
    var maxFileSizeBytes = 10000000;  // 10 MB
    if (file[0].size > maxFileSizeBytes) {
        //alert("The file must not exceed 10 MB");
        console.log("The file exceeded the max size");
        return;
    }

    var data = {
        stepUid: $scope.step.StepUID,
        userName: trContextSvc.getContext().name
    };

    // Upload the file using the Angular File Uploader
    $upload.upload({
        url: '/Project/' + $scope.ProjectID + '/Step/AddAttachment',
        method: 'POST',
        data: data,
        file: file
    }).progress(function (evt) {
        console.log('progress: ' + parseInt(100.0 * evt.loaded / evt.total) + '% file :' + evt.config.file[0].name);
    }).then(function (response) {
        $timeout(function () {
            // file is uploaded successfully
            console.log('file ' + response.config.file[0].name + 'is uploaded successfully.');
            $scope.step.Attachments.push(response.data);
        });
    });
};

Like I said, on a second upload attempt, after a successful one, the AddAttachment(file) function is fired twice with the same file. Only in IE10, so far.

If I choose a file that fails my max size limit, on subsequent button click, the dialog options, noticing the previous filename is already in the box. Choosing it again results in file = "" and then file = [], and this alternates on button presses.

Thanks for your help.

@danialfarid
Copy link
Owner

Can you try adding onclick="this.value = null" to your input and see if that fixes the problem.

@MattWatt
Copy link
Author

Not sure I understand. I know that was one of the fixes I saw mentioned, however I'm not defining my own input, and allowing your directive to create the hidden input tag beneath my button. Is there a way to add it to button so it will get copied down to the hidden element that's being created?

@danialfarid
Copy link
Owner

Can you see if this works:

<input type="file" ng-file-select ng-model="file" ng-file-change="addAttachment(file)"ng-multiple="false"  onclick="this.value = null">

My fix may be broken for IE10 I am trying to find out the issue and don't have access to IE10 atm.

Also make sure you don't have a $scope.$watch on the file model. That would cause uploading twice.

@MattWatt
Copy link
Author

I replaced by button with what you suggested. On my first file upload, everything worked good as usual. Second time I attempted to upload a new file, it still hit my addAttachment() function twice, however, the first time through file was equal to an empty string, and the second time my actual file came through. That did prevent it from uploading it twice, but my function is still getting fired twice for some reason.

The third time I tried to add a file it still uploaded it twice.

@MattWatt
Copy link
Author

Line 210 in the scope.resetOnClick() check where it's trying to do elem[0].value = null isn't appearing to do anything in IE10 while I debug in Visual Studio. This is probably why after my first file upload I still get the previous file's name appearing in the dialog when it opens.

@danialfarid
Copy link
Owner

Yea, I'm gonna do a fix release for this soon.

@danialfarid
Copy link
Owner

It is supposed to call the change twice though since when you click on that button it will reset the value to null so your model object should become empty. Then when you select a file it will reset the value to that file.
So you should ignore the change if there is no file in the model,

@MattWatt
Copy link
Author

That might be where the issue is then. I can see change getting fired twice but both times the "files" property contains the value of my file.

@MattWatt
Copy link
Author

Following everything through the debugger... what I'm seeing is that the resetOnClick() is firing the second time I try to upload a file. This function is calling "updateModel" since the elem[0] has a previous value. This updateModel's $timeout is adding a deferred promise to Angular's deferred array. Then the dialog opens, I choose my file. Then elem's change event gets triggered, which calls "updateModel" with the actual fileList.

Here's where I notice that the $timeout around scope.change() is getting executed, twice for each of the deferred promises, but "files" both time contains my file.

@danialfarid
Copy link
Owner

yea the problem is that you cannot programmatically set the value of an input file type in IE10 so you gotta have onclick="this.value=null" I am gonna make the code to add this to the element instead of binding it to click. For now you can just use input type=file and add that to your input.

@MattWatt
Copy link
Author

I'm wondering how necessary the $timeout is on line 238? It's nested within a $timeout in UpdateModel(). Seems redundant and after removing it things seemed to work well in IE10 and Chrome.

@MattWatt
Copy link
Author

sharing some additional research:

"IE seems to consider a dialog like the file dialog to essentially be blocking I/O: all javascript execution halts while it's open."

The reset $timeout, triggers when the dialog opens, but never executes until the dialog closes, unlike other browsers which still allow scripts to run.

I dumped a bunch of console.log()s into the code and compared IE's sequence of events to Chrome's. The number after the colon is the .length of the relevant file property.

IE10

*** Page Load ***
ngModel $watch val: null 
*** 1st File ***
 click (event): reset 
 change (event) files: 1 
 updateModel files: 1 
 fileModel:1 
 ngModel $watch val: 1 
 change() files: 1 
 addAttachment() files: 1 
 progress: 0% file :dec08-04-1280.jpg 
 progress: 48% file :dec08-04-1280.jpg 
 progress: 97% file :dec08-04-1280.jpg 
 progress: 100% file :dec08-04-1280.jpg 
 progress: 100% file :dec08-04-1280.jpg 
 file dec08-04-1280.jpgis uploaded successfully. 

*** 2nd File ***
 click (event): reset 
 change (event) files: 1 
 updateModel files: 0 
 fileModel:0 
 ngModel $watch val: 0 
 updateModel files: 1 
 fileModel:1 
 ngModel $watch val: 1 
 change() files: 0 
 addAttachment() files: 1 
 change() files: 1 
 addAttachment() files: 1 
 progress: 0% file :TRig3.jpg 
 progress: 0% file :TRig3.jpg 
 progress: 52% file :TRig3.jpg 
 progress: 52% file :TRig3.jpg 
 progress: 100% file :TRig3.jpg 
 progress: 100% file :TRig3.jpg 
 progress: 100% file :TRig3.jpg 
 file TRig3.jpgis uploaded successfully. 
 progress: 100% file :TRig3.jpg 
 file TRig3.jpgis uploaded successfully. 

Chrome39

*** Page Load ***
 click (event): reset
*** 1st File ***
angular-file-upload.js:240 change (event) files: 1
angular-file-upload.js:246 updateModel files: 1
angular-file-upload.js:257 fileModel:1
angular-file-upload.js:219 ngModel $watch val: 1
angular-file-upload.js:260 change() files: 1
testRunCtrl.js:210 addAttachment() files: 1
testRunCtrl.js:232 progress: 6% file :dec08-04-1280.jpg
2testRunCtrl.js:232 progress: 100% file :dec08-04-1280.jpg
testRunCtrl.js:235 file dec08-04-1280.jpgis uploaded successfully.

*** 2nd File ***
angular-file-upload.js:206 click (event): reset
angular-file-upload.js:246 updateModel files: 0
angular-file-upload.js:257 fileModel:0
angular-file-upload.js:219 ngModel $watch val: 0
angular-file-upload.js:260 change() files: 0
angular-file-upload.js:240 change (event) files: 1
angular-file-upload.js:246 updateModel files: 1
angular-file-upload.js:257 fileModel:1
angular-file-upload.js:219 ngModel $watch val: 1
angular-file-upload.js:260 change() files: 1
testRunCtrl.js:210 addAttachment() files: 1
testRunCtrl.js:232 progress: 6% file :TRig3.jpg
2testRunCtrl.js:232 progress: 100% file :TRig3.jpg
testRunCtrl.js:235 file TRig3.jpgis uploaded successfully.

In IE10 the ngModel is updated with the new file before my addAttachment() function is called. Even though the change() function contained no data the first time around, my function will grab whatever is in the ngModel when it's called, meaning both times it contains my file.

Chrome doesn't have this problem because JS isn't halted until the dialog closes.

Commenting out the $timeout around scope.change() resulted in this sequence in IE10

click (event): reset 
 change (event) files: 1 
 updateModel files: 0 
 fileModel:0 
 change() files: 0 
 ngModel $watch val: 0 
 updateModel files: 1 
 fileModel:1 
 change() files: 1 
 addAttachment() files: 1 
 ngModel $watch val: 1 
 progress: 0% file :TRig3.jpg 
 progress: 52% file :TRig3.jpg 
 progress: 100% file :TRig3.jpg 
 progress: 100% file :TRig3.jpg 
 file TRig3.jpgis uploaded successfully. 

danialfarid pushed a commit that referenced this issue Jan 6, 2015
@danialfarid
Copy link
Owner

This should be fixed in version 2.1.1.

@gamebox
Copy link

gamebox commented Feb 14, 2015

Just as clarification, this is only fixed if you do not have a $watch set on files correct?

@danialfarid
Copy link
Owner

no it should work as expected whether you have watch or function.

@gamebox
Copy link

gamebox commented Feb 14, 2015

Interesting, I am still having this issue reported to me by users of IE 10 on Windows 8. I don't have access to a windows machine at home or at the office, so I'm at a little bit of a loss for debugging the issue. And yes, I am on 2.1.1

@SlippySken
Copy link

it seems like i have the same problem on 2.1.1

edit: with 3.0.7 everything is fine

@akshay-bbytes
Copy link

onclick="this.value = null" worked fine for me thanks

@sunnyrainywen
Copy link

I met the question too, does this issue been fixed now?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants