컴포넌트/필드 컴포넌트

DisplayField (디스플레이 필드)

VanillaFront 2026. 9. 14. 18:10

Va.DisplayField — 라벨 + 읽기 전용 값 표시

Va.Display가 순수 표시 필드라면, Va.DisplayField는 그 위에 폼 라벨·검증 메시지 영역을 얹은 완성 폼 필드입니다. Field 계열 아키텍처 그대로, 내부에 Va.Display를 소유하는 Composition 구조. 폼 안 조회 화면의 정석.

  • 클래스: Va.DisplayField  va_component.js:9612
  • short name: displayField
  • 상속: Va.Field (다른 Field 형제들과 같음)
  • 내부 컴포넌트: Va.Display 인스턴스 (fieldComponent)
  • isContainer: true
  • 베이스 CSS: va-field


1. 기본 사용

{
    tagName: 'displayField',
    label: '고객명',
    value: '홍길동'
}

라벨 + 읽기 전용 값 표시가 한 번에 세팅. 다른 폼 필드(InputField, ComboboxField 등)와 규격 통일.


2. Display / InputField(readonly)와의 차이

항목Va.DisplayVa.DisplayFieldVa.InputField(readonly)

폼 라벨
검증 메시지 영역
필수 표시 ✓ (실무엔 잘 안 씀)
DOM 태그 <div> <div> (내부 위임) <input>
HTML 콘텐츠
readonly 강제 옵션
폼 서브밋 값 ✓ (readonly여도)

한 줄 요약: "폼 안 라벨 붙은 읽기 전용 값 표시 필드 — 조회 화면 정석."


3. 주요 속성

Display 전용 (계승)

속성설명

value 표시할 값 (Field 표준 옵션)
text 순수 텍스트 (Display 옵션으로 통과 시)
innerHTML HTML 콘텐츠 (Display 옵션으로 통과 시)

⚠️ readonly 강제 — 코드에서 this.readonly = true 세팅. 옵션으로 false 넘겨도 무시.

라벨 관련 (Field 상속)

속성설명

label 폼 라벨
labelPosition top / bottom / left / right
labelWidth 라벨 폭
noLabel 폼 라벨 숨김
infoButton info 아이콘
required 필수 표시 (실질적 의미 없음 — 표시 전용이라)

검증 (실질 사용 드묾)

속성설명

validation {state, size, message}
validationState success / warning / error
validationMessage 메시지

읽기 전용 필드에 검증 메시지는 활용도가 낮지만, "필수 값이 비어있음" 같은 상황엔 유용할 수 있음.

세부 커스터마이즈 (display 옵션 키)

{
    tagName: 'displayField',
    label: '상태',
    display: {                    // ← 내부 Display에 직접 전달
        innerHTML: '<b>승인 완료</b>'
    }
}

각 Field 계열 옵션 키:

  • InputField → input
  • CheckboxField → checkbox
  • DisplayField → display

4. 이벤트

Display의 이벤트를 재발화 (매우 제한적):

이벤트시그니처발생 시점

select (component, element, evt) 선택 이벤트 (텍스트 선택 등) — 검증 자동 리셋
keydown (component, element, evt) 키다운 — 검증 자동 리셋

주목: focus/blur/click/change 재발화 코드가 없음. 읽기 전용 필드라 실질적으로 이벤트 처리가 필요한 상황이 드물다는 설계 의도.


5. 메서드

값 관리 (Field 상속)

메서드설명

getValue() 내부 Display의 getValue() 위임 (textContent)
setValue(value) Field 상속 — Display의 setValue()가 호출됨

⚠️ setValue()의 위험 — 내부 Display의 setValue()가 element 자식을 통째로 덮는 문제가 있어(element.textContent = value), 초기 구조 훼손 가능. 안전한 방법은 option.value나 option.text 지정.

상태 (Field 상속)

메서드설명

setDisabled(bool) / getDisabled() 비활성화
setReadOnly(bool) / setReadonly(bool) 읽기 전용 (이미 true 강제)
setLabel(label) 폼 라벨 변경
setSize(size) 크기

검증

메서드설명

setValidation(state, message) 검증 표시
clearValidation() 검증 해제

6. 내부 구조

<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">고객명</label>
    </div>
    <div elname="comment" class="field-comment"></div>
    <div elname="fieldDiv" class="field-div">
      <div cpname="field" class="va-display">              ← 내부 Va.Display
        <div class="field-wrapper">
          <div style="border:0px">홍길동</div>              ← 값 (input 아님)
          <div class="focus-line"></div>
        </div>
      </div>
    </div>
  </div>
  <div elname="validationDiv" style="display:none">
    <div class="va-validation">...</div>
  </div>
</div>

핵심: 안쪽이 <input>이 아니라 <div>인 것 외엔 다른 Field 형제와 시각 구조 동일.


7. 언제 쓰나

DisplayField가 맞을 때

  • 폼 안 조회 항목 (편집 없이 값 표시)
  • 상세 화면 — 등록/수정 폼과 시각 규격 통일
  • 자동 생성 값 표시 (주문번호, 생성일 등)
  • 계산 결과 표시 (다른 필드 값 조합)
  • 읽기 전용 상태를 명시적으로 표현

다른 걸 쓸 때

  • 라벨 없이 인라인 → Va.Display
  • 편집 가능하되 잠금 → Va.InputField + readonly: true
  • 폼과 무관한 일반 텍스트 → <div> / Va.Div
  • 긴 텍스트 스크롤 표시 → Va.TextareaField + readonly

8. 흔한 조합 예시

// 표준
{
    tagName: 'displayField',
    label: '고객명',
    value: '홍길동'
}

// HTML 콘텐츠 (내부 display 옵션)
{
    tagName: 'displayField',
    label: '상태',
    display: {
        innerHTML: '<span style="color:green">활성</span>'
    }
}

// 좌측 라벨 (조회 화면 관행)
{
    tagName: 'displayField',
    label: '주문번호',
    labelPosition: 'left',
    labelWidth: 100,
    value: '20240315-001'
}

// 계산 결과 표시
mounted() {
    const a = Number(this.getRef('a').getValue());
    const b = Number(this.getRef('b').getValue());
    this.getRef('sum').value = a + b;
    this.getRef('sum').update();
}

// 서버 응답 표시
onLoad(view, ok, res) {
    if (ok) {
        view.getRef('createdAt').value = res.data.info.createdAt;
        view.getRef('createdAt').update();
    }
}

9. 실전 예 — 주문 상세 조회 폼

class OrderDetail extends Va.View {
    async mounted() {
        const orderId = this.getParams().orderId;
        const res = await OrderService.get(this, { orderId });

        if (res.result) {
            const info = res.data.info;
            this.getRef('orderId').value  = info.orderId;
            this.getRef('custName').value = info.custName;
            this.getRef('amount').value   = info.amount.toLocaleString() + '원';
            this.getRef('createdAt').value = info.createdAt;

            // HTML 콘텐츠로 상태 강조
            const statusColor = info.status === 'DONE' ? 'green' : 'orange';
            this.getRef('status').fieldComponent.innerHTML =
                `<span style="color:${statusColor}">${info.statusName}</span>`;

            // 각 필드 update() 트리거
            ['orderId', 'custName', 'amount', 'createdAt', 'status'].forEach(ref => {
                this.getRef(ref).update();
            });
        }
    }

    config() {
        return {
            tagName: 'page',
            tags: [{
                tagName: 'panel',
                tags: [
                    { tagName: 'h2', innerHTML: '주문 상세' },
                    {
                        tagName: 'div',
                        layout: 'ds-flex fd-column gap-s',
                        tags: [
                            {
                                tagName: 'displayField',
                                ref: 'orderId',
                                label: '주문번호',
                                labelPosition: 'left',
                                labelWidth: 120
                            },
                            {
                                tagName: 'displayField',
                                ref: 'custName',
                                label: '고객명',
                                labelPosition: 'left',
                                labelWidth: 120
                            },
                            {
                                tagName: 'displayField',
                                ref: 'amount',
                                label: '결제 금액',
                                labelPosition: 'left',
                                labelWidth: 120
                            },
                            {
                                tagName: 'displayField',
                                ref: 'status',
                                label: '상태',
                                labelPosition: 'left',
                                labelWidth: 120
                            },
                            {
                                tagName: 'displayField',
                                ref: 'createdAt',
                                label: '주문일시',
                                labelPosition: 'left',
                                labelWidth: 120
                            }
                        ]
                    },
                    {
                        tagName: 'button',
                        text: '수정',
                        appearance: 'primary',
                        onClick: 'onEdit'
                    }
                ]
            }]
        };
    }
}

포인트:

  • 좌측 라벨 정렬로 조회 화면다움 강조
  • 다른 폼 필드(InputField 등)와 라벨 폭 통일 가능
  • 상태는 HTML 콘텐츠로 색상 강조
  • 수정 버튼 클릭 시 편집 폼(InputField 사용)으로 전환

10. 알아두면 좋을 주의사항

  1. readonly: true 강제 — Display와 동일. 편집 가능으로 만들 수 없음.
  2. 폼 서브밋에 값 참여 안 됨  <input> 아님. 서버 전송은 별도 처리.
  3. setValue() 내부 구조 훼손 위험 — Display의 문제가 그대로 전파됨. option.value나 component.fieldComponent.innerHTML = ...; component.update() 권장.
  4. value vs text vs innerHTML  value는 Field 표준, text/innerHTML은 display 옵션으로 전달 시 우선.
  5. 옵션 키 display — 세부 커스터마이즈용.
  6. 이벤트 매우 제한적  select/keydown만 재발화. 실질 활용 드묾.
  7. 검증 자동 리셋 있음  select/keydown 시. 다만 편집 안 되는 필드라 검증 활용도 낮음.
  8. required: true는 별표만 표시 — 실질적 의미 없음 (편집 불가).
  9. 라벨 폭 통일이 조회 화면의 핵심  labelPosition: 'left' + labelWidth로 다른 필드와 정렬.
  10. HTML 콘텐츠 세팅 시  component.fieldComponent.innerHTML = value; component.update() 패턴이 안전.

11. displayField vs inputField(readonly) vs display 선택

상황추천

폼 안 조회 항목 (라벨 함께) displayField
라벨 없이 인라인 display
편집 가능하되 임시 잠금 inputField + readonly: true
폼 서브밋 값 필요 inputField + readonly: true
HTML 콘텐츠 표시 displayField + display.innerHTML
긴 텍스트 textareaField + readonly: true

"조회 화면 = displayField, 잠긴 편집 화면 = inputField readonly" — 명확한 원칙.


참고

'컴포넌트 > 필드 컴포넌트' 카테고리의 다른 글

LabelField (라벨 필드)  (0) 2026.09.14
Label (라벨)  (0) 2026.09.14
Display (디스플레이)  (0) 2026.09.14
FileDropUploadField (파일드롭 업로드 필드)  (0) 2026.09.14
FileDropUpload (파일드롭 업로드)  (0) 2026.09.14