12

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

Tony Lâmpada
  • 5,301
  • 6
  • 38
  • 50

8 Answers8

6

I come to this page for same issue with Angular 2

And finally fixed like this:

<input type="file" 
    [accept]="extAccepts" 
    [multiple]="(maxFiles > 1)" />

Note: both file type (extAccepts) and maxFiles are reading from component as @input() from the user.

Hope it will help for someone!

Ali Adravi
  • 21,707
  • 9
  • 87
  • 85
4

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

sbedulin
  • 4,102
  • 24
  • 34
2

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.

cyberwombat
  • 38,105
  • 35
  • 175
  • 251
1

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.

Michael Kang
  • 52,003
  • 16
  • 103
  • 135
  • 3
    Thanks, didn't know about ng-attr. Now this is weird, look: I tried adding `ng-attr-multiple="{{allow_multiple}}"` on my . 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 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 05 '14 at 16:29
0

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.

Rasmus
  • 4,190
  • 7
  • 22
  • 32
0

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

Wilson Mendes
  • 261
  • 4
  • 5
  • 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 05 '14 at 14:50
0

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

Wilson Mendes
  • 261
  • 4
  • 5
  • 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 05 '14 at 14:51
0

Solution is pretty simple since you are using directive or component - just manipulate DOM on the right moment. Take a glance here:

app.component('myComponent', {
    templateUrl: 'tmpl.html',
    bindings: {
        str: '@'
    },
    controller: function ($element) {
        this.$postLink = function () {
            $element.find('input').attr('multiple', 'multiple');
        }
    }
}
anatol
  • 1,680
  • 2
  • 24
  • 47