Components: Need to support input type="file" in md-input

Created on 21 Dec 2016  路  9Comments  路  Source: angular/components

Bug, feature request, or proposal:

Proposal

What is the expected behavior?

support type="file" in input

What is the current behavior?

type="file" is not supported

What are the steps to reproduce?

Which versions of Angular, Material, OS, browsers are affected?

All Angular/Material versions

Most helpful comment

@da45 <input type='file' /> are notoriously hard to style, so you're better off using a md-button to trigger a hidden <input type='file' />.

Maybe that's what you are requesting here?

Here's a simple wrapper with a hidden input and a button:

// inputFile.ts
import {Component, Output, EventEmitter, ViewChild, ElementRef, Input} from '@angular/core';

@Component({
    'moduleId': module.id,
    'selector': 'input-file',
    'templateUrl': './file.tpl.html'
})
export class InputFile {
    @Input() accept: string;
    @Output() onFileSelect: EventEmitter<File[]> = new EventEmitter();

    @ViewChild('inputFile') nativeInputFile: ElementRef;

    private _files: File[];

    get fileCount(): number { return this._files && this._files.length || 0; }

    onNativeInputFileSelect($event) {
        this._files = $event.srcElement.files;
        this.onFileSelect.emit(this._files);
    }

    selectFile() {
        this.nativeInputFile.nativeElement.click();
    }
}
// file.tpl.html
<span>
    <input [accept]="accept" type="file" (change)="onNativeInputFileSelect($event)" #inputFile hidden />
    <button type="button" md-raised-button (click)="selectFile()">
        <md-icon>file_upload</md-icon>
        <ng-content *ngIf="!fileCount" select=".nofiles"></ng-content>
        <span *ngIf="fileCount">
            <span>{{fileCount}}</span>
            <ng-content select=".selected"></ng-content>
        </span>
    </button>
</span>

And use it like:

<input-file (onFileSelect)="onFileSelect($event)" [accept]="'image/*'">
        <span class="nofiles">Choose file</span>
        <span class="selected">Files selected</span>
    </input-file>

All 9 comments

@da45 <input type='file' /> are notoriously hard to style, so you're better off using a md-button to trigger a hidden <input type='file' />.

Maybe that's what you are requesting here?

Here's a simple wrapper with a hidden input and a button:

// inputFile.ts
import {Component, Output, EventEmitter, ViewChild, ElementRef, Input} from '@angular/core';

@Component({
    'moduleId': module.id,
    'selector': 'input-file',
    'templateUrl': './file.tpl.html'
})
export class InputFile {
    @Input() accept: string;
    @Output() onFileSelect: EventEmitter<File[]> = new EventEmitter();

    @ViewChild('inputFile') nativeInputFile: ElementRef;

    private _files: File[];

    get fileCount(): number { return this._files && this._files.length || 0; }

    onNativeInputFileSelect($event) {
        this._files = $event.srcElement.files;
        this.onFileSelect.emit(this._files);
    }

    selectFile() {
        this.nativeInputFile.nativeElement.click();
    }
}
// file.tpl.html
<span>
    <input [accept]="accept" type="file" (change)="onNativeInputFileSelect($event)" #inputFile hidden />
    <button type="button" md-raised-button (click)="selectFile()">
        <md-icon>file_upload</md-icon>
        <ng-content *ngIf="!fileCount" select=".nofiles"></ng-content>
        <span *ngIf="fileCount">
            <span>{{fileCount}}</span>
            <ng-content select=".selected"></ng-content>
        </span>
    </button>
</span>

And use it like:

<input-file (onFileSelect)="onFileSelect($event)" [accept]="'image/*'">
        <span class="nofiles">Choose file</span>
        <span class="selected">Files selected</span>
    </input-file>

@fredrikredflag Thanks a lot for your great support, I think this will help me to go ahead in my project.
nevertheless, it will be good if one day md-input supports type="file" :)

md-input the compoenet has been deprecated - we now use md-input-container
https://material.angular.io/components/component/input

@fredrikredflag as @EladBezalel md-input is deprecated. Any chances You could update Your code to use md-input-container? For now proper Material 2 implementation isn't on road map so Your solution is best we have.

@Misiu md-input isn't used in my example. It uses a native input, so it's still valid.

Hi,
I made my own, similar to the implementation above.
Available here: https://gist.github.com/merlosy/ab33dd7edaacfd92d6c9a5daea0a1240
Working fine so far and look like material field :)

note: the snippet posted by @fredrikredflag doesn't work on firefox as event.srcElement isn't available - using event.target instead should be more reliable cross-browser.

A simple and latest material version snippet would be:

<button mat-button (click)="inputFile.click()">Import file</button> {{ inputFile.value }}
<input #inputFile type="file" [style.display]="'none'">

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

_This action has been performed automatically by a bot._

Was this page helpful?
0 / 5 - 0 ratings

Related issues

3mp3ri0r picture 3mp3ri0r  路  3Comments

dzrust picture dzrust  路  3Comments

michaelb-01 picture michaelb-01  路  3Comments

vitaly-t picture vitaly-t  路  3Comments

xtianus79 picture xtianus79  路  3Comments