According to this issue: github.com/driftyco/ionic/issues/6628 we needed a solution to the problem. It ended up in a little custom component. Maybe this will be a temporary solution to others too or it could be basis for an ionic included solution.
Attention: As this was my first typescript, angular 2 component and also the first project with these tools, please be merciful if it includes bad practices or other mistakes. It is more a first draft than a final solution. Any improvements and fixes are welcome. We used the common practice for this styling issues and translate it to Angular. A hidden input element combined with a button doing the work.
Usage is simple just use the newly created tag ant tell it which ionic icon to use for the button. Also a callback must be defined which is executed after files are selected (FileList is passsed as parameter to it):
<upload-button [btnCallback]="addCallback" [btnStyle]="icon"></upload-button>
import {IONIC_DIRECTIVES} from "ionic-angular";
import {Component, ElementRef, Input, Inject, ViewChild, Renderer} from "angular2/core";
import {Log} from "../../log";
@Component({
directives: [IONIC_DIRECTIVES],
selector: "upload-button",
template: `<button (click)="callback($event)" clear>
<ion-icon name="{{btnStyle}}"></ion-icon>
</button>
<input type="file" (change)="filesAdded($event)" style="display: none" multiple #input />`
})
/**
* Upload button component.
*
* As native input elements with type file are diffcult to style, it is common
* practice to hide them and trigger the needed events manually as it done here.
* A button is is used for user interaction, next to the hidden input.
*/
export class UploadButton {
/**
* The callback executed when button pressed, set by parent
*/
@Input()
private btnStyle: String;
/**
* The callback executed when files are selected, set by parent
*/
@Input()
private btnCallback: Function;
/**
* Native upload button (hidden)
*/
@ViewChild("input")
private nativeInputBtn: ElementRef;
/**
* Constructor
* @param {Renderer} renderer for invoking native methods
* @param {Log} logger instance
*/
constructor(private renderer: Renderer, @Inject(Log) private logger: Log) {}
/**
* Callback executed when the visible button is pressed
* @param {Event} event should be a mouse click event
*/
public callback(event: Event): void {
this.logger.debug("upload-button callback executed");
// trigger click event of hidden input
let clickEvent: MouseEvent = new MouseEvent("click", {bubbles: true});
this.renderer.invokeElementMethod(
this.nativeInputBtn.nativeElement, "dispatchEvent", [clickEvent]);
}
/**
* Callback which is executed after files from native popup are selected.
* @param {Event} event change event containing selected files
*/
public filesAdded(event: Event): void {
let files: FileList = this.nativeInputBtn.nativeElement.files;
this.logger.debug("Added files", files);
this.btnCallback(files);
}
}