如何在角材质中使用输入类型文件

问题描述 投票:0回答:11

如何在角材质中使用输入类型文件

嗨,我正在使用有角度的材料进行设计。当我访问 Angular Material 网站时,没有输入类型文件元素。有人知道这个吗。

angular angular-material material-design
11个回答
119
投票

如果您想要的只是一个显示良好的文件输入按钮,这里有一个解决方法。

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


50
投票

Angular Material 尚不支持文件上传的解决方法。 有其他方法可以实现此目的。例如使用外部库。

angular-material-fileupload链接到 npm 包

支持的功能

  • 拖放
  • 常见上传
  • 进度条
  • 文件大小等等...

ngx-material-file-input链接到存储库

支持的功能

  • ngx-mat-file-input
    组件,在 Angular Material 内部使用
    mat-form-field
  • a
    FileValidator
    maxContentSize
    ,限制文件大小
  • a
    ByteFormatPipe
    以人类可读的格式格式化文件大小
  • 还有更多小功能...

更新

如果您只需要无需外部库的解决方法,请参阅此处的答案 https://stackoverflow.com/a/53546417/6432698


14
投票

在@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 */
}

输出:


8
投票

我建议您查看@angular-material-components/file-input

它非常符合角度材料标准。


5
投票

使用 ::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>


2
投票
您也可以使用此方法(使用 Tailwind CSS)。这里有两个输入。第一个是透明文件输入。文件输入是 z-index 的正面。背面有另一个输入(matInput)。

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

*点击输入即可直接打开文件对话框。


1
投票
这很有趣,但在我的例子中,它与 attr 绑定一起使用

[attr.type]="'file'"

,而不是直接设置属性 
type="file"

    


0
投票
如果您不想使用一些奇怪的解决方法,那么就不要将

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

0
投票
创建指令 -

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>
    

0
投票
我找到了一个快速简单的方法来解决这个问题。

我使文件的输入看起来像文本的输入。

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

0
投票
有一个更现代的 API

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
  });
};
    
© www.soinside.com 2019 - 2024. All rights reserved.