web-dev-qa-db-fra.com

Téléchargement de fichier avec un matériau angulaire

J'écris une application web avec AngularJS et angular-material. Le problème est qu'il n'y a pas de composant intégré pour l'entrée de fichier en matériau angulaire. (Je pense que le téléchargement de fichiers ne correspond pas à la conception du matériau, mais j'en ai besoin dans mon application)

Avez-vous une bonne solution à ce problème? 

36
weiway

Je trouve un moyen d'éviter de styler mon propre bouton de choix de fichier.

Parce que j'utilise flowjs pour un téléchargement pouvant être repris, je peux utiliser la directive " flow-btn " de ng-flow , qui donne un bouton de choix de fichier avec un style de conception de matériau. .

Notez que placer l’élément d’entrée dans un bouton md ne fonctionnera pas.

6
weiway

Belle solution de leocaseiro

<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>

 enter image description here

Voir dans codepen

41
Radin Reth

Basé sur cette réponse . Il m'a fallu un certain temps pour que cette approche fonctionne, alors j'espère que ma réponse fera gagner du temps à quelqu'un.

DEMO sur CodePen

Directive: 

angular.module('app').directive('apsUploadFile', apsUploadFile);

function apsUploadFile() {
    var directive = {
        restrict: 'E',
        templateUrl: 'upload.file.template.html',
        link: apsUploadFileLink
    };
    return directive;
}

function apsUploadFileLink(scope, element, attrs) {
    var input = $(element[0].querySelector('#fileInput'));
    var button = $(element[0].querySelector('#uploadButton'));
    var textInput = $(element[0].querySelector('#textInput'));

    if (input.length && button.length && textInput.length) {
        button.click(function (e) {
            input.click();
        });
        textInput.click(function (e) {
            input.click();
        });
    }

    input.on('change', function (e) {
        var files = e.target.files;
        if (files[0]) {
            scope.fileName = files[0].name;
        } else {
            scope.fileName = null;
        }
        scope.$apply();
    });
}

upload.file.template.html

<input id="fileInput" type="file" class="ng-hide">
<md-button id="uploadButton"
           class="md-raised md-primary"
           aria-label="attach_file">
    Choose file
</md-button>
<md-input-container md-no-float>
    <input id="textInput" ng-model="fileName" type="text" placeholder="No file chosen" ng-readonly="true">
</md-input-container>
13
Juniper

de jameswyse à https://github.com/angular/material/issues/3310

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>

MANETTE

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

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

Travaillé pour moi.

12
Chris L

Un autre exemple de la solution… .. ressemblera à ce qui suit  enter image description here

Lien CodePen il.

  <choose-file layout="row">
    <input id="fileInput" type="file" class="ng-hide">
    <md-input-container flex class="md-block">
      <input type="text" ng-model="fileName" disabled>
      <div class="hint">Select your file</div>
    </md-input-container>
    <div>
      <md-button id="uploadButton" class="md-fab md-mini">
        <md-icon class="material-icons">attach_file</md-icon>
      </md-button>
    </div>
  </choose-file>   

.directive('chooseFile', function() {
    return {
      link: function (scope, elem, attrs) {
        var button = elem.find('button');
        var input = angular.element(elem[0].querySelector('input#fileInput'));

        button.bind('click', function() {
          input[0].click();
        });

        input.bind('change', function(e) {
          scope.$apply(function() {
            var files = e.target.files;
            if (files[0]) {
              scope.fileName = files[0].name;
            } else {
              scope.fileName = null;
            }
          });
        });
      }
    };
  });

J'espère que ça aide!

12
Artyom Pranovich

Une autre solution piratée, bien que pourrait être un peu plus propre en implémentant un bouton Proxy: 

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();
  };
};
2
Dombi Soma

Vous pouvez changer le style en encapsulant l'entrée dans une étiquette et changer l'affichage d'entrée en aucun. Ensuite, vous pouvez spécifier le texte que vous souhaitez afficher dans un élément span. Remarque: ici, j'ai utilisé le style bootstrap 4 (btn btn-outline-primary). Vous pouvez utiliser n'importe quel style. 

<label class="btn btn-outline-primary">
      <span>Select File</span>
      <input type="file">
</label>

input {
  display: none;
}
0
MAhmed

En ajoutant à toutes les réponses ci-dessus (c’est pourquoi j’en ai fait un wiki de communauté), il vaut probablement mieux marquer input<type="text"> avec tabindex="-1", surtout si vous utilisez readonly au lieu de disabled (et peut-être le <input type="file">, bien qu’il soit caché, toujours dans le document, apparemment). Les étiquettes n'ont pas agi correctement lors de l'utilisation des combinaisons de touches tabulation/entrée, mais le bouton l'a fait. Par conséquent, si vous copiez l'une des solutions proposées sur cette page, vous souhaiterez peut-être apporter ces modifications.

0
Guy Schalnat

Pour Angular 6+:

HTML:

<input #csvInput hidden="true" type="file" onclick="this.value=null" (change)="csvInputChange($event)" accept=".csv"/>
<button mat-flat-button color="primary" (click)="csvInput.click()">Choose Spreadsheet File (CSV)</button>

Méthode du composant:

  csvInputChange(fileInputEvent: any) {
    console.log(fileInputEvent.target.files[0]);
  }

Remarque: Ceci filtre pour autoriser uniquement les fichiers .csv.

0
rynop