Va.FileDropUploadField — 라벨 + 드래그앤드롭 파일 업로드
Va.FileDropUpload가 순수 드롭 영역이라면, Va.FileDropUploadField는 그 위에 폼 라벨·필수 표시·검증 메시지를 얹은 완성 폼 필드입니다. Field 계열 아키텍처 그대로, 내부에 Va.FileDropUpload를 소유하는 Composition 구조. 폼 안에서 드래그앤드롭 업로드가 필요할 때 정석.
- 클래스: Va.FileDropUploadField — va_component.js:12653
- short name: fileDropUploadField
- 상속: Va.Field (다른 Field 형제들과 같음)
- 내부 컴포넌트: Va.FileDropUpload 인스턴스 (fieldComponent)
- isContainer: true
- 베이스 CSS: va-field
1. 기본 사용
{
tagName: 'fileDropUploadField',
label: '첨부파일',
text: '파일을 여기 놓으세요',
fileDropUpload: { // ← 내부 세부 옵션
fileType: 'binary'
},
required: true,
onFiledrop: 'onFileDropped'
}
라벨 + 검증 + 드롭 영역이 한 번에 세팅.
2. FileDropUpload / 다른 Field와의 차이
항목Va.FileDropUploadVa.FileDropUploadFieldVa.FileField
| 폼 라벨 | ✕ | ✓ | ✓ |
| 검증 메시지 | ✕ | ✓ | ✓ |
| 필수 표시(별표) | ✕ | ✓ | ✓ |
| info 툴팁 | ✕ | ✓ | ✓ |
| UI 형태 | 드롭 영역 | 드롭 영역 (내부 위임) | 파일 표시 + 두 버튼 |
| 드래그앤드롭 | ✓ | ✓ | ✕ |
| fileType 옵션 | ✓ | ✓ (fileDropUpload 통해) | ✕ |
| 파일 다이얼로그 지원 | ✕ | ✕ | ✓ |
한 줄 요약: "폼 안 라벨 붙은 드래그앤드롭 업로드 필드."
3. 주요 속성
FileDropUpload 전용 (계승)
속성기본값설명
| text | — | 드롭 영역 안내 텍스트 |
| innerHTML | — | HTML 안내 콘텐츠 |
⚠️ fileType은 직접 옵션에 없음 — 내부 FileDropUpload 옵션이라 fileDropUpload 옵션 객체로 전달해야 합니다:
{
tagName: 'fileDropUploadField',
label: 'CSV 업로드',
fileDropUpload: {
fileType: 'text' // 여기서 지정
}
}
fileType 없으면 내부 FileDropUpload의 기본값 'binary'가 적용.
라벨 관련 (Field 상속)
속성설명
| label | 폼 라벨 |
| labelPosition | top / bottom / left / right |
| labelWidth | 라벨 폭 |
| noLabel | 폼 라벨 숨김 |
| infoButton | info 아이콘 |
| required | 필수 표시 |
검증
속성설명
| validation | {state, size, message} |
| validationState | success / warning / error |
| validationMessage | 메시지 |
세부 커스터마이즈 (fileDropUpload 옵션 키)
{
tagName: 'fileDropUploadField',
label: '이미지',
fileDropUpload: { // ← 내부 FileDropUpload에 직접 전달
fileType: 'binary',
text: '이미지를 드래그하세요'
}
}
각 Field 계열 옵션 키:
- FileField → file
- ImageFileField → (있다면) imageFile
- FileDropUploadField → fileDropUpload
4. 스타일 관련 특이사항
생성자에서 흥미로운 코드가 있습니다:
let fieldOption = {...option};
fieldOption.style = null; // style 제거
fieldOption.layout = null; // layout 제거
⚠️ fieldOption이 실제로는 활용 안 되는 로직 — 이 후 optionField를 별도로 만들어 사용. 데드 코드일 가능성. 다만 style/layout이 내부 컴포넌트로 전파되지 않도록 하려던 의도로 보입니다.
함의: style/layout 옵션은 Field 껍데기에만 적용되고, 안의 드롭 영역에는 별도 스타일을 fieldDropUpload 옵션 통해 전달해야 할 수도 있음. 실제 렌더링 결과 확인 후 조정 필요.
5. 이벤트
FileDropUpload의 이벤트를 재발화:
이벤트시그니처발생 시점
| filedrop | (component, element, result, evt) | 파일 드롭 후 읽기 완료. result가 텍스트 또는 DataURL |
| change | (component, element, files, evt) | 드롭 시 dispatch. files는 FileList |
filedrop 콜백 예시
onFileDropped(field, el, result, evt) {
// result는 fileType에 따라 텍스트 또는 DataURL
const files = field.fieldComponent.fieldElement.files;
console.log('드롭된 파일:', files);
// 서버 전송
const formData = new FormData();
for (let i = 0; i < files.length; i++) {
formData.append('files', files[i]);
}
UploadService.send(this, formData, ...);
}
주의: Field 표준 이벤트(focus/blur/click 등)는 재발화 코드에 없음. 필요하면 component.fieldComponent에 직접 리스너.
6. 메서드
상태 (Field 상속)
메서드설명
| setDisabled(bool) / getDisabled() | 비활성화 |
| setReadOnly(bool) / setReadonly(bool) | 읽기 전용 |
| setLabel(label) | 폼 라벨 변경 |
| setSize(size) | 크기 |
검증
메서드설명
| setValidation(state, message) | 검증 표시 |
| clearValidation() | 검증 해제 |
주의: 파일 조회 편의 메서드가 별도로 없음. getFiles() 같은 메서드도 명시적으로 없어, 파일은 component.fieldComponent.fieldElement.files로 접근.
7. 내부 구조
<div elname="element" class="va-field [vertical|horizontal]" field="true">
<div elname="inner" class="field-inner">
<div elname="labelDiv" class="label-div">
<label cpname="label">첨부파일 <span class="required">*</span></label>
</div>
<div elname="comment" class="field-comment"></div>
<div elname="fieldDiv" class="field-div">
<div cpname="field" class="va-file-upload-div" ← 내부 Va.FileDropUpload
tabindex="0">
<div class="file-upload-div-inner"
style="width:100%; height:100%">
<span>파일을 여기 놓으세요</span>
<input type="file" style="display:none">
</div>
</div>
</div>
</div>
<div elname="validationDiv" style="display:none">
<div class="va-validation">...</div>
</div>
</div>
8. 언제 쓰나
FileDropUploadField가 맞을 때
- 폼 안 드래그앤드롭 업로드 — 첨부 자료, 이미지 등록 폼
- 라벨·필수·검증이 필요한 드롭 UI
- CSV/JSON 가져오기 폼 (fileType: 'text')
- 이미지·바이너리 업로드 폼 (fileType: 'binary')
다른 걸 쓸 때
- 라벨 없이 인라인 → Va.FileDropUpload
- 표준 파일 선택 다이얼로그 → Va.FileField
- 이미지 미리보기 통합 → Va.ImageFileField
- 간단 첨부 버튼 → Va.FileButton
9. 흔한 조합 예시
// 표준 (바이너리)
{
tagName: 'fileDropUploadField',
label: '첨부파일',
text: '파일을 여기 놓으세요',
fileDropUpload: { fileType: 'binary' },
required: true,
onFiledrop: 'onDrop'
}
// CSV 파싱용
{
tagName: 'fileDropUploadField',
label: 'CSV 파일',
text: 'CSV 파일을 드래그하세요',
fileDropUpload: { fileType: 'text' },
infoButton: {
tooltip: 'UTF-8 인코딩된 CSV 파일만 지원'
},
onFiledrop: 'onCsvDrop'
}
// 좌측 라벨
{
tagName: 'fileDropUploadField',
label: '자료 첨부',
labelPosition: 'left',
labelWidth: 120,
text: '파일을 놓으세요',
fileDropUpload: {
fileType: 'binary',
style: { // 드롭 영역 스타일
width: '100%',
height: '150px',
border: '2px dashed gray',
borderRadius: '8px',
display: 'flex',
alignItems: 'center',
justifyContent: 'center'
}
}
}
// 아이콘 포함
{
tagName: 'fileDropUploadField',
label: '이미지 업로드',
fileDropUpload: {
innerHTML: '<div style="text-align:center"><i class="ico_cloud_upload" style="font-size:48px"></i><br>이미지를 드래그하세요</div>',
fileType: 'binary'
}
}
10. 실전 예 — CSV 가져오기 폼
class ProductImport extends Va.View {
onCsvDrop(field, el, result, evt) {
// result는 CSV 텍스트 전체
try {
const lines = result.split('\n').filter(l => l.trim());
const headers = lines[0].split(',').map(h => h.trim());
const data = [];
for (let i = 1; i < lines.length; i++) {
const values = lines[i].split(',');
const row = {};
headers.forEach((h, idx) => row[h] = values[idx]?.trim());
data.push(row);
}
if (data.length === 0) {
field.setValidation('error', '데이터가 없습니다');
return;
}
field.clearValidation();
this.getRef('grid').setData(data);
this.getRef('summary').setValue(`${data.length}건 로드됨`);
} catch (e) {
field.setValidation('error', 'CSV 파싱 실패: ' + e.message);
}
}
onImport(btn, el, evt) {
const data = this.getRef('grid').getData();
if (data.length === 0) {
new Va.Alert({ title: '알림', message: '먼저 CSV를 로드하세요' }).show(this);
return;
}
ProductService.bulkImport(this, { products: data }, (view, ok) => {
if (ok) new Va.Alert({ title: '완료', message: '가져오기 완료' }).show(view);
});
}
config() {
return {
tagName: 'page',
tags: [{
tagName: 'panel',
tags: [
{ tagName: 'h2', innerHTML: '상품 대량 가져오기' },
{
tagName: 'fileDropUploadField',
ref: 'csv',
label: 'CSV 파일',
text: 'CSV 파일을 여기 놓으세요',
fileDropUpload: {
fileType: 'text',
style: {
width: '100%',
height: '150px',
border: '2px dashed var(--colorNeutralStroke)',
borderRadius: '8px',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
cursor: 'pointer'
}
},
required: true,
onFiledrop: 'onCsvDrop'
},
{
tagName: 'inputField',
ref: 'summary',
label: '로드 상태',
readonly: true
},
{
tagName: 'grid',
ref: 'grid',
columns: [/* 동적 */],
style: { height: '400px' }
},
{
tagName: 'button',
text: '가져오기 실행',
appearance: 'primary',
onClick: 'onImport'
}
]
}]
};
}
}
흐름:
- 사용자가 CSV 파일 드롭 → filedrop 이벤트
- 텍스트 파싱해 그리드에 표시
- 검증 실패 시 인라인 에러 메시지
- "가져오기" 버튼으로 서버 전송
11. 알아두면 좋을 주의사항
- fileType은 fileDropUpload 옵션으로 전달 — Field 옵션엔 없음. 필수 지정 아니면 'binary' 기본.
- style/layout은 Field 껍데기에 적용 — 드롭 영역 스타일은 fileDropUpload.style로 별도 전달.
- Field 표준 이벤트(focus/blur 등) 재발화 없음 — filedrop/change만. 필요하면 fieldComponent에 직접.
- getFiles() 편의 메서드 없음 — component.fieldComponent.fieldElement.files 직접 접근.
- filedrop 이벤트는 파일마다 반복 — 여러 파일 드롭 시 각 파일에 대해 dispatch. 전체 목록은 change로.
- 디렉토리 자동 무시 — 폴더 드롭해도 파일만 처리.
- 파일 다이얼로그 없음 — 클릭으로 파일 선택 창이 안 열림. 표준 파일 선택도 필요하면 FileField 병행.
- change 시 검증 자동 리셋 없음 — 필요하면 콜백에서 명시적 clearValidation().
- 레이아웃/스타일 개발자 책임 — 기본 스타일 최소. 드롭 영역 크기·테두리 명시 지정.
- 모바일 지원 제한 — 드래그앤드롭은 데스크톱 위주.
- 접근성 취약 — 스크린리더 대응 약함. 라벨 명시 권장.
- fieldOption 관련 데드 코드 — 소스에 미사용 로직 있음. 실제 동작에 영향 없음.
12. fileDropUploadField vs fileField vs imageFileField 선택
상황추천
| 폼 안 드래그앤드롭 업로드 | fileDropUploadField |
| CSV/JSON 가져오기 폼 | fileDropUploadField + fileType: 'text' |
| 표준 파일 첨부 폼 | fileField |
| 이미지 미리보기 폼 | imageFileField (있다면) |
| 간단 첨부 (버튼만) | fileField |
| 인라인 (라벨 없이) | fileDropUpload |
참고
- API 문서 페이지: https://vanillafront.com/docs.html?theme=light#main#apifiledropuploadfield
- 연관: Va.FileDropUpload(내부), Va.FileField(대체 가능한 표준 파일 필드)
'컴포넌트 > 필드 컴포넌트' 카테고리의 다른 글
| DisplayField (디스플레이 필드) (0) | 2026.09.14 |
|---|---|
| Display (디스플레이) (0) | 2026.09.14 |
| FileDropUpload (파일드롭 업로드) (0) | 2026.09.14 |
| ImageFile (이미지파일) (1) | 2026.09.14 |
| FileField (파일필드) (1) | 2026.09.14 |