javascript
This commit is contained in:
parent
7092583b0a
commit
981e7ff244
1 changed files with 67 additions and 23 deletions
|
@ -1,37 +1,81 @@
|
|||
import { ApplicationController } from './application_controller';
|
||||
import { hide, show } from '@utils';
|
||||
|
||||
export class FileInputResetController extends ApplicationController {
|
||||
static targets = ['reset'];
|
||||
|
||||
declare readonly resetTarget: HTMLElement;
|
||||
static targets = ['fileList'];
|
||||
declare fileListTarget: HTMLElement;
|
||||
|
||||
connect() {
|
||||
this.on('change', (event) => {
|
||||
if (event.target == this.fileInput) {
|
||||
this.showResetButton();
|
||||
super.connect();
|
||||
this.updateFileList();
|
||||
this.element.addEventListener('change', (event) => {
|
||||
if (
|
||||
event.target instanceof HTMLInputElement &&
|
||||
event.target.type === 'file'
|
||||
) {
|
||||
this.updateFileList();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
reset(event: Event) {
|
||||
updateFileList() {
|
||||
const files = this.fileInput?.files ?? [];
|
||||
this.fileListTarget.innerHTML = '';
|
||||
|
||||
const deleteLabel =
|
||||
this.element.getAttribute('data-delete-label') || 'Delete';
|
||||
|
||||
Array.from(files).forEach((file, index) => {
|
||||
const container = document.createElement('li');
|
||||
container.style.display = 'flex';
|
||||
container.style.alignItems = 'center';
|
||||
|
||||
const deleteButton = this.createDeleteButton(deleteLabel, index);
|
||||
container.appendChild(deleteButton);
|
||||
|
||||
const listItem = document.createElement('div');
|
||||
listItem.textContent = file.name;
|
||||
listItem.style.marginLeft = '8px';
|
||||
|
||||
container.appendChild(listItem);
|
||||
this.fileListTarget.appendChild(container);
|
||||
});
|
||||
}
|
||||
|
||||
createDeleteButton(deleteLabel: string, index: number) {
|
||||
const button = document.createElement('button');
|
||||
button.textContent = deleteLabel;
|
||||
button.classList.add(
|
||||
'fr-btn',
|
||||
'fr-btn--tertiary',
|
||||
'fr-btn--sm',
|
||||
'fr-icon-delete-line'
|
||||
);
|
||||
|
||||
button.addEventListener('click', (event) => {
|
||||
event.preventDefault();
|
||||
this.fileInput.value = '';
|
||||
hide(this.resetTarget);
|
||||
this.removeFile(index);
|
||||
});
|
||||
|
||||
return button;
|
||||
}
|
||||
|
||||
showResetButton() {
|
||||
show(this.resetTarget);
|
||||
removeFile(index: number) {
|
||||
const files = this.fileInput?.files;
|
||||
if (!files) return;
|
||||
|
||||
const dataTransfer = new DataTransfer();
|
||||
Array.from(files).forEach((file, i) => {
|
||||
if (index !== i) {
|
||||
dataTransfer.items.add(file);
|
||||
}
|
||||
});
|
||||
|
||||
if (this.fileInput) this.fileInput.files = dataTransfer.files;
|
||||
this.updateFileList();
|
||||
}
|
||||
|
||||
private get fileInput() {
|
||||
const inputs =
|
||||
this.element.querySelectorAll<HTMLInputElement>('input[type="file"]');
|
||||
if (inputs.length == 0) {
|
||||
throw new Error('No file input found');
|
||||
} else if (inputs.length > 1) {
|
||||
throw new Error('Multiple file inputs found');
|
||||
}
|
||||
return inputs[0];
|
||||
private get fileInput(): HTMLInputElement | null {
|
||||
return this.element.querySelector(
|
||||
'input[type="file"]'
|
||||
) as HTMLInputElement | null;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue