Skip to content

Instantly share code, notes, and snippets.

@wall-street-dev
Created July 13, 2023 17:02
Show Gist options
  • Save wall-street-dev/305bb51e1e711d1f4aa6e09be4c15202 to your computer and use it in GitHub Desktop.
Save wall-street-dev/305bb51e1e711d1f4aa6e09be4c15202 to your computer and use it in GitHub Desktop.
import { Observable } from 'rxjs';
const createInput = (acceptType: string) => {
const input = document.createElement('input');
input.type = 'file';
input.accept = `.${acceptType}`;
input.style.display = 'none';
return input;
};
/**
* Creates an Observable that emits the selected file from a file input.
*
* The function generates a hidden file input element which automatically opens
* a file selection dialog. It then waits for the user to select a file, and when they do,
* it emits that file through the Observable. Once the file is selected or the selection dialog
* is cancelled, the file input element is removed from the DOM and the Observable completes.
*
* @export
* @param {string} [acceptType='json'] - The type of the files that the file input should accept.
* Default is 'json'.
* @returns {Observable<File>} An Observable that emits the selected file.
* Completes after the file is selected or the dialog is cancelled.
*/
export function fromSelectedFile(acceptType = 'json'): Observable<File> {
return new Observable(observer => {
const input = createInput(acceptType);
const removeInputAndComplete = () => {
document.body.removeChild(input);
observer.complete();
};
input.oncancel = removeInputAndComplete;
input.onchange = (event: Event) => {
const target = event.target as HTMLInputElement;
if (target.files?.length) {
const file = target.files[0];
observer.next(file);
}
removeInputAndComplete();
};
document.body.appendChild(input);
input.click();
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment