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

Don't call ngf-change with an empty files parameter #764

Closed
lookfirst opened this issue May 27, 2015 · 20 comments
Closed

Don't call ngf-change with an empty files parameter #764

lookfirst opened this issue May 27, 2015 · 20 comments

Comments

@lookfirst
Copy link
Contributor

@danialfarid What I'm seeing is that ngf-change is being called TWICE. Once when you click the button and the file chooser dialog opens and once when the dialog closes after selecting a file.

I added this to your fiddle...

    $scope.upload = function (files) {
        alert('called from upload. files is: ' + files);

Whatever is calling it shouldn't call it the first time. There is no reason to call $scope.upload if files is null. This would allow me to remove the null check and simplify things greatly.

@pimpin
Copy link

pimpin commented May 27, 2015

Notice that, when you select over sized files (using the optional ngf-max-size attribute), it also fire ngf-change with an empty $file Array. So it's hard to make difference on controller side between those 2 use cases.
[EDIT] silly me ! To check any over sized files, I just need to test the second argument that is $rejectedFiles

@danialfarid
Copy link
Owner

I have explained here why it needs to be fired on click: #761 (comment)

@lookfirst
Copy link
Contributor Author

There is no reason to call ngf-change with an empty files parameter. Nothing has changed.

@danialfarid
Copy link
Owner

It would only call it if a file is already selected and it resets the model value to null.

@lookfirst
Copy link
Contributor Author

Maybe I need to submit a pull request cause you don't seem to understand. Whatever the expression is in ngf-changed is, which is typically a function... does not need to be called if the parameter that is passed to it is null.

@danialfarid
Copy link
Owner

If you cancel the popup file select, it should call ngf-change with null value.
I might consider adding an option to not reset the model on file click, but that would not allow you to select the same file again or clear the model when the user cancels the popup.

@lookfirst
Copy link
Contributor Author

"If you cancel the popup file select, it should call ngf-change with null value."

No, it shouldn't. A cancel should not modify state. If there was a value there before, it will be cleared out and that is against the previous sentence.

@danialfarid
Copy link
Owner

Here are related issues:
#527
#451
#499

@lookfirst
Copy link
Contributor Author

Right, that just goes to show that your API design has issues.

@danialfarid
Copy link
Owner

Yea I explained here #761 (comment) that there is no way to detect user's cancel, that's why we need to reset the value on click.

@lookfirst
Copy link
Contributor Author

Call another method. pseudo code:

ngf-change="expression($files)" ngf-cancel="cancel()"

if (!$files) {
  cancel()
}

@danialfarid
Copy link
Owner

I think that makes it more complicated, ngf-change needs to be close to ng-model behaviour, when you cancel the popup ng-model is being set to null so ngf-change should be called too.
I think a null check is easy enough that doesn't require adding another directive attribute to the api.

@lookfirst
Copy link
Contributor Author

Right, but the problem is that ngf-change gets called in 3 different situations and for 3 different reasons. Open, Cancel and File Select. That is impossible to case for correctly.

@danialfarid
Copy link
Owner

So what is your suggestion here?
Instead of ngf-cancel you could just have a check

if (!$files) {}

any other solutions you have in mind?

danialfarid pushed a commit that referenced this issue Jun 4, 2015
@danialfarid
Copy link
Owner

I have added ngf-reset-on-click and ngf-reset-model-on-click options to version 5.0.0 to control this behaviour.

@lookfirst
Copy link
Contributor Author

"Setting ngf-reset-model-on-click will not reset the model when you click on the file select, that would make reseting model when the user cancels the select popup impossible in some browsers."

Your defaults are conceived in a backwards fashion. By default, you don't want to reset the model on cancel. It is a cancel event, nothing should change.

@danialfarid
Copy link
Owner

Setting it to true by default will break cross browser support.
By default it should behave the same cross browser.

@lookfirst
Copy link
Contributor Author

Oh right. The option that you'd had to close 20 issues over is a much better default.

On Jun 4, 2015, at 11:31 AM, Danial Farid notifications@github.com wrote:

Setting it to true by default will break cross browser support.
By default it should behave the same cross browser.


Reply to this email directly or view it on GitHub.

@v29neil
Copy link

v29neil commented Jun 12, 2015

Had the same issue-
Fixed it by using. Not sure if this is the correct way
<button ngf-select="" ng-model="files" ngf-multiple="false" >Upload </button>

In controller-
$scope.$watch('files', function (files) { console.log(files); if( (files != null) ){ console.log('file uploading'); } });

@Harlantr
Copy link

2017 update:

I have a form that is set up to validate on whether or not a file was uploaded. When a user would cancel out of the dialog box, the upload field would be invalid because the ng-model had changed to null.

Since the API has since changed from the suggestions in this issue but this page is still the top result when searching "ng-file-upload change empty," I figured I'd note my solution:

I simply hooked into the ngf-before-model-change function, set a temporary controller variable, and reset my "real" value when ngf-change was called. It looks a little like this:

form.html

<a id="fileUpload"
     href=""
     name="fileUpload"
     class="fa fa-2x fa-upload"
     ng-model="ctrl.file"
     ngf-select
     ngf-min-size="1"
     ngf-change="ctrl.uploadFile($file)"
     ngf-before-model-change="ctrl.setTmpFile($file)"
     required>
</a>

controller.js

setTmpFile (newFile) {
    // If new file exists, set the temporary variable
    // newFile will be null if the user cancels out of the dialog box
    if(newFile){
        this.tmpFile = newFile;
    };
};

uploadFile (newFile, index) {
    // Set the "real" model to the temporary file
    this.file = this.tmpFile;

    ...
    Do other stuff
};

Now, the ng-model variable ctrl.file is either a real file (the user selected one in the dialog) or the file it was previously (the user cancels out of the box).

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

5 participants