Join the Stack Overflow Community
Stack Overflow is a community of 6.8 million programmers, just like you, helping each other.
Join them; it only takes a minute:
Sign up

I need an upload form field that may or may not allow the user to select more than one file.

I know I can do something like:

<input type="file" multiple ng-if="allow_multiple">
<input type="file" ng-if="!allow_multiple">

But, we know that is not ideal.

I tried

<input type="file" ng-multiple="allow_multiple">

But that doesn't work.

It seems that AngularJS has no such ngMultiple directive, but everyone is using it anyway (or am I missing something?)

Anyway, what is the best way to accomplish that?

EDIT: From thw answers so far it really seems like there's no pretty way to do this. I opened this issue on their tracker, let's see what we get :-) https://github.com/angular/angular.js/issues/7714

share|improve this question
    
have you considered ngUpload it has multiple as bool option? – Dalorzo Jun 4 '14 at 17:25
    
ng-multiple works only for select. – Fals Jun 4 '14 at 17:26
    
@Dalorzo, you mean this, right? github.com/twilson63/ngUpload. Will take a look. – Tony Lâmpada Jun 4 '14 at 17:34
    
@Fals, do you know where can I find it (ng-multiple for <select>'s) in the official documentation? – Tony Lâmpada Jun 4 '14 at 17:35
    
you could try this one github.com/danialfarid/angular-file-upload – Dalorzo Jun 4 '14 at 17:40

The easiest way is to write your own ngMultiple directive.

HTML (relevant):

<label><input type="checkbox" ng-model="allowMultiple"> Allow multiple</label>
<hr>
<input
  type="file"
  class="hide"
  accept="image/*"
  ng-multiple="allowMultiple">

JS:

angular
    .module('app', [])
    .controller('appCtrl', function($scope) {
        $scope.allowMultiple = false;
    })
    .directive('ngMultiple', function () {
        return {
            restrict: 'A',
            scope: {
                ngMultiple: '='
            },
            link: function (scope, element) {
                var unwatch = scope.$watch('ngMultiple', function (newValue) {
                    if(newValue) {
                        element.attr('multiple', 'multiple');
                    } else {
                        element.removeAttr('multiple');
                    }
                });
            }
        };
    });

Plunker

share|improve this answer

Besides the difficulty of doing this there is also the issue that some browser will not evaluate multiple="false" (Safari 8 on file input for ex). So the multiple attribute needs to be conditionally written.

I would wrap your html in a directive and conditionally apply the attribute within the directive such as:

var input = elem.find('input');
if(condition)
  input.attr('multiple', 'true');

Where the condition could be any directive attribute.

share|improve this answer

I am on mobile, sorry for the short answer.

I would hide two different file inputs, one with the multiple attribute and one without. You can use the ng-if directive to achieve that.

Edit: I'm so sorry, seems like you don't want to do it that way, even though it's completely valid. You could write your own directive for it however, it's really simple.

share|improve this answer

You can use ngSwitch directive for this. Take a look in AngularJs documentation for more details.

https://docs.angularjs.org/api/ng/directive/ngSwitch

In this demo example the directive switch between input file with and without multiple based in a scope param passed for directive using ngSwitch directive.

Demo using ngSwitch

share|improve this answer
    
Thanks Wilson. It solves the problem, but it's not exactly what I'm looking for. It's no different than using ng-if (I have to declare two inputs anyway) – Tony Lâmpada Jun 5 '14 at 14:50

Another idea is to use ngShow/ngHide for this. In this demo example input file is show/hide based in param and have a directive for get input value(s) and set in a $scope param.

Demo using ngShow + directive

share|improve this answer
    
Thanks Wilson. It solves the problem, but it's not exactly what I'm looking for. It's no different than using ng-if (I have to declare two inputs anyway) – Tony Lâmpada Jun 5 '14 at 14:51

Try using ng-attr-

 ng-attr-class="{{someBoolean && 'class-when-true' || 'class-when-false' }}"

If you prefix any attribute with ng-attr-, then the compiler will strip the prefix, and add the attribute with its value bound to the result of the angular expression from the original attribute value.

share|improve this answer
1  
Thanks, didn't know about ng-attr. Now this is weird, look: I tried adding ng-attr-multiple="{{allow_multiple}}" on my <input>. It has no effect on it, regardless of the value of allow_multiple. Now if I add ng-attr-bolinha="{{allow_multiple}}", then it adds an attribute bolinha="false" or bolinha="true" on the <input> But you know, even if it added multiple="false", the browser doesn't care for the "false" attribute, it would still allow for multiple file selection just because "multiple" is present. Mmm, I have the feeling this should be easier. I'm heading to the issue tracker... – Tony Lâmpada Jun 5 '14 at 16:29

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.