wake-up-neo.com

Dateiupload von <input type = "file">

Bei der Verwendung von "angle 2 beta" kann ich scheinbar keinen <input type="file"> zum Laufen bringen.

Bei der Diagnose kann ich die bidirektionale Bindung für andere types sehen, wie z. B. text.

<form>
    {{diagnostic}}
    <div class="form-group">
        <label for="fileupload">Upload</label>
        <input type="file" class="form-control" [(ngModel)]="model.fileupload">
    </div>
</form>

In meiner TypeScript-Datei habe ich die folgende Diagnosezeile:

get diagnostic() { return JSON.stringify(this.model); }

Könnte es sein, dass es nicht darum geht, JSON zu sein? Der Wert ist null.

Ich kann den Wert von input nicht wirklich überprüfen. Wenn der Text neben "Datei auswählen ..." aktualisiert wird, sehe ich aus irgendeinem Grund keine Unterschiede im DOM.

57
PascalVKooten

Ich denke, dass es nicht unterstützt wird. Wenn Sie sich diese DefaultValueAccessor-Direktive ansehen, lesen Sie https://github.com/angular/angular/blob/master/modules/angr2/src/common/forms/directives/default_value_accessor.ts#L23 . Sie werden sehen, dass der zum Aktualisieren des gebundenen Elements verwendete Wert $event.target.value ist.

Dies gilt nicht für Eingaben mit dem Typ file, da das Dateiobjekt stattdessen $event.srcElement.files erreicht werden kann.

Weitere Informationen finden Sie in diesem Bericht: https://plnkr.co/edit/ozZqbxIorjQW15BrDFrg?p=info :

@Component({
  selector: 'my-app',
  template: `
    <div>
      <input type="file" (change)="onChange($event)"/>
    </div>
  `,
  providers: [ UploadService ]
})
export class AppComponent {
  onChange(event) {
    var files = event.srcElement.files;
    console.log(files);
  }
}
66
@Component({
  selector: 'my-app',
  template: `
    <div>
      <input name="file" type="file" (change)="onChange($event)"/>
    </div>
  `,
  providers: [ UploadService ]
})
export class AppComponent {
  file: File;
  onChange(event: EventTarget) {
        let eventObj: MSInputMethodContext = <MSInputMethodContext> event;
        let target: HTMLInputElement = <HTMLInputElement> eventObj.target;
        let files: FileList = target.files;
        this.file = files[0];
        console.log(this.file);
    }

   doAnythingWithFile() {
   }

}
38
Ashish Doneriya

Es gibt eine etwas bessere Möglichkeit, auf angehängte Dateien zuzugreifen. Sie können template Referenzvariable verwenden, um eine Instanz des Eingabeelements abzurufen.

Hier ist ein Beispiel, das auf der ersten Antwort basiert:

@Component({
  selector: 'my-app',
  template: `
    <div>
      <input type="file" #file (change)="onChange(file.files)"/>
    </div>
  `,
  providers: [ UploadService ]
})

export class AppComponent {
  onChange(files) {
    console.log(files);
  }
}

Hier ist eine example App , um dies in Aktion zu demonstrieren.

Vorlagenreferenzvariablen können nützlich sein, z. Sie können über @ViewChild direkt im Controller darauf zugreifen.

26
Frelseren

Eine andere Möglichkeit, eine Vorlagenreferenzvariable und ViewChild zu verwenden, wie von Frelseren vorgeschlagen:

import { ViewChild } from '@angular/core';

@Component({
  selector: 'my-app',
  template: `
    <div>
      <input type="file" #fileInput/>
    </div>
  `
})  
export class AppComponent {
  @ViewChild("fileInput") fileInputVariable: any;
  randomMethod() {
    const files = this.fileInputVariable.nativeElement.files;
    console.log(files);
  }
}

Siehe auch https://stackoverflow.com/a/40165524/4361955

5
jhujhul

Versuchen Sie es mit dieser kleinen Bibliothek, die mit Angular 5.0.0 funktioniert

Schnellstart-Beispiel mit ng2-file-upload 1.3.0:

Der Benutzer klickt auf die Schaltfläche "Benutzerdefiniert", die den Upload-Dialog aus dem ausgeblendeten Eingabetyp = "Datei" auslöst. Der Upload wurde automatisch gestartet, nachdem eine einzelne Datei ausgewählt wurde. 

app.module.ts:

import {FileUploadModule} from "ng2-file-upload";

your.component.html:

...
  <button mat-button onclick="document.getElementById('myFileInputField').click()" >
    Select and upload file
  </button>
  <input type="file" id="myFileInputField" ng2FileSelect [uploader]="uploader" style="display:none">
...

your.component.ts:

import {FileUploader} from 'ng2-file-upload';
...    
uploader: FileUploader;
...
constructor() {
   this.uploader = new FileUploader({url: "/your-api/some-endpoint"});
   this.uploader.onErrorItem = item => {
       console.error("Failed to upload");
       this.clearUploadField();
   };
   this.uploader.onCompleteItem = (item, response) => {
       console.info("Successfully uploaded");
       this.clearUploadField();

       // (Optional) Parsing of response
       let responseObject = JSON.parse(response) as MyCustomClass;

   };

   // Asks uploader to start upload file automatically after selecting file
  this.uploader.onAfterAddingFile = fileItem => this.uploader.uploadAll();
}

private clearUploadField(): void {
    (<HTMLInputElement>window.document.getElementById('myFileInputField'))
    .value = "";
}

Alternative lib, funktioniert in Angular 4.2.4, erfordert jedoch einige Problemumgehungen, um Angular 5.0.0 zu übernehmen 

2
Yurii Bratchuk

Wenn Sie ein komplexes Formular mit mehreren Dateien und anderen Eingaben haben, ist hier eine Lösung, die Nice mit ngModel spielt.

Sie besteht aus einer Dateieingabekomponente, die eine einfache Dateieingabe umschließt und die ControlValueAccessor-Schnittstelle implementiert, um sie für ngModel verwendbar zu machen. Die Komponente macht das FileList-Objekt für ngModel verfügbar.

Diese Lösung basiert auf diesem Artikel.

Die Komponente wird wie folgt verwendet:

<file-input name="file" inputId="file" [(ngModel)]="user.photo"></file-input>
<label for="file"> Select file </label>

Hier ist der Komponentencode:

import { Component, Input, forwardRef } from '@angular/core';
import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms';

const noop = () => {
};

export const CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR: any = {
    provide: NG_VALUE_ACCESSOR,
    useExisting: forwardRef(() => FileInputComponent),
    multi: true
};

@Component({
  selector: 'file-input',
  templateUrl: './file-input.component.html',
  providers: [CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR]
})
export class FileInputComponent {

  @Input()
  public name:string;

  @Input()
  public inputId:string;

  private innerValue:any;

  constructor() { }

  get value(): FileList {
    return this.innerValue;
  };

  private onTouchedCallback: () => void = noop;
  private onChangeCallback: (_: FileList) => void = noop;

  set value(v: FileList) {
    if (v !== this.innerValue) {
      this.innerValue = v;
      this.onChangeCallback(v);
    }
  }

  onBlur() {
    this.onTouchedCallback();
  }

  writeValue(value: FileList) {
    if (value !== this.innerValue) {
      this.innerValue = value;
    }
  }

  registerOnChange(fn: any) {
    this.onChangeCallback = fn;
  }

  registerOnTouched(fn: any) {
    this.onTouchedCallback = fn;
  }

  changeFile(event) {
    this.value = event.target.files;
  }
}

Und hier ist die Komponentenvorlage:

<input type="file" name="{{ name }}" id="{{ inputId }}" multiple="multiple" (change)="changeFile($event)"/>
0
Jens

probiere einfach (onclick)="this.value = null"

fügen Sie auf Ihrer HTML-Seite eine Onclick-Methode hinzu, um den vorherigen Wert zu entfernen, damit der Benutzer dieselbe Datei erneut auswählen kann. 

0
yogesh chavan