如何在角材质中使用输入类型文件
嗨,我正在使用有角度的材料进行设计。当我访问 Angular Material 网站时,没有输入类型文件元素。有人知道这个吗。
如果您想要的只是一个显示良好的文件输入按钮,这里有一个解决方法。
HTML
<button type="button" mat-raised-button (click)="fileInput.click()">Choose File</button>
<input hidden (change)="onFileSelected()" #fileInput type="file" id="file">
组件
onFileSelected() {
const inputNode: any = document.querySelector('#file');
if (typeof (FileReader) !== 'undefined') {
const reader = new FileReader();
reader.onload = (e: any) => {
this.srcResult = e.target.result;
};
reader.readAsArrayBuffer(inputNode.files[0]);
}
}
受到 Angular Material Github Issue 评论的启发 https://github.com/angular/material2/issues/3262#issuecomment-309000588
Angular Material 尚不支持文件上传的解决方法。 有其他方法可以实现此目的。例如使用外部库。
angular-material-fileupload:链接到 npm 包
支持的功能:
ngx-material-file-input:链接到存储库
支持的功能:
ngx-mat-file-input
组件,在 Angular Material 内部使用 mat-form-field
FileValidator
与 maxContentSize
,限制文件大小ByteFormatPipe
以人类可读的格式格式化文件大小更新
如果您只需要无需外部库的解决方法,请参阅此处的答案 https://stackoverflow.com/a/53546417/6432698
在@JackMorrissey's answer的基础上,我找到了一个更简化的解决方案:
HTML:
<button type="button" mat-raised-button (click)="fileInput.click()">Choose File</button>
<input hidden (change)="onFileSelected($event)" #fileInput type="file">
<span class="file-name">{{selectedFile?.name}}</span>
TypeScript:
selectedFile: any = null;
onFileSelected(event: any): void {
this.selectedFile = event.target.files[0] ?? null;
}
CSS:
.file-name {
margin-left: 1rem; /* or whatever margin you require */
}
输出:
使用 ::file-selector-button 将类型文件的默认输入元素设置为看起来像角度材质按钮更有意义。此外,这种方式考虑了用户体验,让用户知道要上传的文件已通过显示文件名添加到表单中。
附注样式是在检查后从声明中复制的 角垫凸起按钮
input[type="file"]::file-selector-button {
box-shadow: 0px 3px 1px -2px rgb(0 0 0 / 20%), 0px 2px 2px 0px rgb(0 0 0 / 14%), 0px 1px 5px 0px rgb(0 0 0 / 12%);
background: #ffd740;
box-sizing: border-box;
position: relative;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
cursor: pointer;
outline: none;
border: none;
-webkit-tap-highlight-color: transparent;
display: inline-block;
white-space: nowrap;
text-decoration: none;
vertical-align: baseline;
text-align: center;
margin: 0;
min-width: 64px;
line-height: 36px;
padding: 0 16px;
border-radius: 4px;
overflow: visible;
transform: translate3d(0, 0, 0);
transition: background 400ms cubic-bezier(0.25, 0.8, 0.25, 1), box-shadow 280ms cubic-bezier(0.4, 0, 0.2, 1);
margin: 1rem;
}
/* fallback for older browsers supporting the -webkit prefix */
input[type="file"]::-webkit-file-upload-button {
box-shadow: 0px 3px 1px -2px rgb(0 0 0 / 20%), 0px 2px 2px 0px rgb(0 0 0 / 14%), 0px 1px 5px 0px rgb(0 0 0 / 12%);
background: #ffd740;
box-sizing: border-box;
position: relative;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
cursor: pointer;
outline: none;
border: none;
-webkit-tap-highlight-color: transparent;
display: inline-block;
white-space: nowrap;
text-decoration: none;
vertical-align: baseline;
text-align: center;
margin: 0;
min-width: 64px;
line-height: 36px;
padding: 0 16px;
border-radius: 4px;
overflow: visible;
transform: translate3d(0, 0, 0);
transition: background 400ms cubic-bezier(0.25, 0.8, 0.25, 1), box-shadow 280ms cubic-bezier(0.4, 0, 0.2, 1);
margin: 1rem;
font-weight: 500;
}
<form>
<label for="fileUpload">Add file</label>
<input type="file" id="fileUpload">
</form>
<mat-form-field class="w-full">
<input
type="file"
class="absolute top-0 z-10 h-full w-full cursor-pointer opacity-0"
accept=".jpeg,.jpg,.png"
/>
<mat-label>{{ matLabel }}</mat-label>
<input
matInput
cdkFocusInitial
class="z-0"
/>
<mat-icon matSuffix class="mr-2">cloud_upload</mat-icon>
<mat-hint class="mat-form-field-hint-end"
>JPEG / JPG / PNG</mat-hint
>
</mat-form-field>
*点击输入即可直接打开文件对话框。
[attr.type]="'file'"
,而不是直接设置属性
type="file"
input
放入
mat-form-field
中。您可以将其放置在
mat-form-field
之外,但仍将值包含在
FormGroup
中。检查示例
<form [formGroup]="someForm" (ngSubmit)="onSubmit()">
<!--input outside the form-field-->
<input type="file" (Change)="onChange($event)"/>
<mat-form-field>
<!--input inside the form-field-->
<input matInput formControlName="someFCN">
</mat-form-field>
<button mat-raised-button>Submit</button>
</form>
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
someForm: FormGroup;
constructor(private formBuilder: FormBuilder) {}
ngOnInit(): void {
this.someForm = this.formBuilder.group({
someFCN: [{ value:'', disabled: false },Validators.required],
file: { value:'', disabled: false }
});
}
onChange(event: Event) {
/*not sure what you want to do with file, i'll just set
selected file´s name as value, but obviously u can do much more than just get file´s name.*/
this.someForm.controls['file'].setValue(event.target.files[0].name);
}
onSubmit() {
return this.someForm.getRawValue();
}
import { Directive, ElementRef, EventEmitter, Inject, Output } from '@angular/core';
import { DOCUMENT } from '@angular/common';
@Directive({
selector: '[appFileUpload]'
})
export class FileUploadDirective {
@Output() fileContent: EventEmitter<ArrayBuffer | string> = new EventEmitter();
constructor(private elementRef: ElementRef, @Inject(DOCUMENT) private document: Document) {
this.elementRef.nativeElement.addEventListener('click', () => {
const input = this.document.createElement('input');
input.type = 'file';
input.onchange = ev => {
const file = (ev.target as HTMLInputElement).files?.item(0);
const reader = new FileReader();
reader.onload = e => {
this.fileContent.next(reader.result!);
input.value = '';
};
switch (file?.type) {
case 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet':
reader.readAsArrayBuffer(file!);
break;
default:
reader.readAsText(file!);
}
};
input.click();
input.remove();
});
}
}
然后像-一样使用它
<button appFileUpload (fileContent)="uploadDump($event)" mat-menu-item><mat-icon>upload_file</mat-icon></button>
我使文件的输入看起来像文本的输入。
HTML:
<mat-form-field>
<mat-label>Select file</mat-label>
<input matInput readonly type="text" id="fakeFileInput" (click)="hiddenInput.click()">
<input hidden type="file" accept=".csv" #hiddenInput (change)="GetFileOnLoad($event)">
<mat-icon matSuffix>folder_open</mat-icon>
</mat-form-field>
打字稿:
public GetFileOnLoad(event: any) {
var file = event.target.files[0];
var element = document.getElementById("fakeFileInput") as HTMLInputElement | null;
if(element != null) {
element.value = file?.name;
}
Blob.text
可以用更简单的方式做到这一点:
<button mat-button (click)="fileInput.click()">Choose File</button>
<input type="file" #fileInput hidden (change)="onFileSelected($event)">
onFileSelected = (event: Event & { target: HTMLInputElement }) => {
event.target.files?.[0]?.text().then(text => {
// use text
});
};