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 type
s 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.
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);
}
}
@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() {
}
}
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.
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
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
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)"/>
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.