Material: feat: add file upload component

Created on 17 Jun 2015  路  21Comments  路  Source: angular/material

I need to file input component and this doesn't fit to material design

Is their any way I can use md-button for file input?

duplicate feature

Most helpful comment

If you use a <label> instead of <md-button> and reference the for="input-file-id" to your <input type="file">, you don't need to bind your click, save some JS. Work just fine:

<input class="ng-hide" id="input-file-id" multiple type="file" />
<label for="input-file-id" class="md-button md-raised md-primary">Choose Files</label>

All 21 comments

:+1: I needed this recently as well.

Bit of a hack, but you can get it working by hiding the input and proxying the click events to the input. Something like this:

HTML:

<input id="fileInput" name="file" type="file" class="ng-hide" multiple>
<md-button id="uploadButton" class="md-raised md-primary"> Choose Files </md-button>

Link Function

link (scope, element, attrs) {
  const input   = element.find('#fileInput');
  const button = element.find('#uploadButton');

  if (input.length && button.length) {
    button.click((e) => input.click());
  }
}

@jameswyse
Thanks, your tip code might suffice this time

Actually it wouldn't work on apple devices, triggering click on file input doesn't call "choose file" dialog

Another hacked solution, though might be a little cleaner by implementing a Proxy button:

HTML:

<input id="fileInput" type="file">
<md-button class="md-raised" ng-click="upload()">
  <label>AwesomeButtonName</label>
</md-button>

JS:

app.controller('NiceCtrl', function ( $scope) {
  $scope.upload = function () {
    angular.element(document.querySelector('#fileInput')).click();
  };
};

If you use a <label> instead of <md-button> and reference the for="input-file-id" to your <input type="file">, you don't need to bind your click, save some JS. Work just fine:

<input class="ng-hide" id="input-file-id" multiple type="file" />
<label for="input-file-id" class="md-button md-raised md-primary">Choose Files</label>

@leocaseiro +1

@leocaseiro Thx, I'll try

@leocaseiro Did you try implementing something to show the selected file in the page

Hi @unnieTron, yes, I did!

It worked great. You can see also on #2151 some more examples or alternatives...

@leocaseiro +1

this was a great solution, but label does not seem to respect .md-primary for different themes. for me its always blue (the default theme)

@randallmeeker if you force with md-colors works for you? I'm sorry, I need to investigate a little deeper.

<input class="ng-hide" id="input-file-id" multiple type="file" />
<label for="input-file-id" class="md-button md-raised md-primary" md-colors="{color: 'primary'}">Choose Files</label>

My config is like this one and is seems working just fine:

$mdThemingProvider.theme('default')
    .primaryPalette('indigo', {
         'default': '900'
    })
    .accentPalette('red');

@leocaseiro thanks a bunch. I was unaware of the md-colors directive which will help a ton.

This might have been fixed.

<md-button class='md-raised md-primary' id='upload' multiple='false' ngf-multiple='true' ngf-select='upload($files, $file, $event)' type='file'>
    Upload
  </md-button>

seems to work as expected

@fme-samuelbirk

You are using ng-file-upload

yep @dinusuresh

@leocaseiro found this looking for a solution for NG2 and it worked

Ran in to this same issue, so I hacked together a quick solution without having to make extra directives / etc.. Basically, render the regular HTML dialog, but with the ugly browse button BEHIND the cute material button. This is better than hiding the input control all together because you still can see the file name to let the user know which file they picked. Only using position:relative and z-index, so it should work on even the oldest browsers supported by angularjs 1.x.

HTML:

 <label class="md-secondary md-raised md-button bring-forward" md-ink-ripple for="xFile">
      <span>Select File</span>
 </label>
 <input type="file" ngf-select ng-model="xFile" name="xFile" id="xFile" class="file-input-hide">

CSS:

 .file-input-hide {
     position: relative;
     left: -6em;
 }
 .bring-forward {
     z-index:10;
 }

@leocaseiro Thanks for a great example - but I inherited some code with a md-button tag-directive, with some attributes like 'on-upload', 'on-complete', 'url' and so on. How to use these data?

@joergenv this is quite an old issue. Please try asking on Stack Overflow, Gitter, or the AngularJS Material forums with a link back to the related comments in this issue.

Was this page helpful?
0 / 5 - 0 ratings