detail-button
목록의 한 행에 대해 상세 화면을 다양한 형태(모달, 탭, 새창)로 열 수 있는 공통 버튼 컴포넌트입니다. grid 내부나 외부 어디에서든 재사용이 가능합니다.
파일 위치는 src/components/plugins/grid/detail-button.vue 입니다(검색과 무관하므로 grid 플러그인 소속). 전역 자동 등록(unplugin-vue-components)이라 import 없이 <detail-button> 으로 바로 씁니다.
props
| 이름 | 타입 | 기본값 | 설명 |
|---|---|---|---|
row | Object | 해당 row 의 데이터 객체. 그리드 안에서는 params.data | |
label | string | 엔티티명. 버튼 문구("{label} 상세")와 모달 제목에 함께 쓰입니다 | |
text | string | 버튼 문구만 직접 지정. 생략하면 "{label} 상세" | |
comp | Component | 실제로 렌더링될 상세 컴포넌트 객체 (markRaw 권장) | |
component-name | string | 상세 컴포넌트 이름. 모달 id 로 .modal 이 붙어 쓰입니다 | |
route-name | string | tab / window 로 열 때 쓸 라우트 이름 (routes.ts 와 일치해야 함). popup 전용이면 생략 가능 | |
back-to | string | 상세에서 목록으로 돌아갈 경로 | |
types | Array | ['popup', 'tab'] | 여는 방식. 'popup', 'tab', 'window'. 첫 항목이 주 버튼이 됩니다 |
popup-only | Boolean | false | true 면 types 를 무시하고 모달로만 엽니다 |
id-key | String | 'id' | row 에서 식별자를 꺼낼 키 |
callback | Function | null | 모달이 저장/삭제/닫힘으로 끝난 뒤 실행 |
params | Object | 상세로 전달할 추가 파라미터. 라우트 파라미터로도 합쳐집니다 | |
popup-content-style | Object | {width: '800px'} | 모달 컨테이너 스타일 |
동작상 알아둘 것
callback은 모달로 열었을 때만 호출됩니다. tab / window 로 열어 수정하면 목록이 자동 갱신되지 않습니다.params는 라우트 파라미터로도 합쳐집니다.user-detail처럼path: ':type/:id'인 라우트는:params="{type: TYPE}"가 없으면 tab·window 열기가 실패합니다.- 앱 설정에서 탭 뷰(
appTagsView)가 꺼져 있으면'tab'은 목록에서 자동으로 빠집니다. 남는 방식이 없으면'popup'으로 대체됩니다. route-name라우트가 없으면'tab'·'window'가 선택지에서 자동으로 빠지고 모달로만 엽니다. 개발자 콘솔에 어떤 이름을 못 찾았는지 경고가 한 번 출력됩니다.row가 비어 있거나id-key값이 없으면 버튼이 비활성 상태로 그려집니다.
라벨이 길면 text 로 버튼 문구만 따로 준다
label 은 모달 제목(800px)과 버튼 문구를 겸합니다. Action 컬럼은 보통 150px 라, 설명적인 긴 이름을 label 에 넣으면 버튼이 깨집니다.
<!-- ❌ 30자짜리 라벨 → 150px 버튼에 "…캐시 목록 상세" 가 들어가지 않는다 -->
<detail-button label="메시지 타겟 아이템에 대한 직접 선택된 타겟 캐시 목록" />
<!-- ✅ 제목은 설명적으로, 버튼은 짧게 -->
<detail-button label="메시지 타겟 아이템에 대한 직접 선택된 타겟 캐시 목록" text="캐시 상세" />NeoSQL 로 화면을 생성하면 label 에 DB 테이블 comment 가 들어가는 경우가 있습니다. comment 는 설명문이라 제목에는 맞아도 버튼에는 안 맞으니, 생성 후 짧은 이름으로 다듬거나 text 를 함께 지정하세요.
예시. grid 내부에서 사용법
<nv-grid-col headerName="Action" :width="150" pinned="right" :cellStyle="grid.style.center" :cellClass="'actions-button-cell'">
<template v-slot:render="{params}">
<detail-button :row="params.data"
label="정보"
route-name="user-detail"
component-name="user-detail"
:comp="detailComponent"
back-to="/home"
id-key="id"
:callback="retrieve"
/>
</template>
</nv-grid-col>행 클릭과 같이 써도 안전하다
pinned="right" 컬럼은 nv-grid 가 행 클릭 대상에서 자동 제외하고, 셀 안의 버튼 클릭도 행 클릭으로 새지 않습니다. @nv-row-clicked="openDetail" 과 이 버튼을 함께 둬도 상세가 두 번 열리지 않습니다. 자세한 규칙은 nv-grid 의 Row Click 참고.
모바일에서는 이 Action 컬럼이 기본으로 숨겨집니다 (좁은 화면에서의 Action 컬럼).
상세 페이지 열기 타입별 사용법
Popup 타입 (모달)
vue<detail-button :row="params.data" :types="['popup']" component-name="banner-detail" // 실제 상세 컴포넌트 경로 :comp="detailComponent" // 상세 컴포넌트 객체 :callback="retrieve" // 모달 닫힐 때 실행할 함수 />Window 타입 (새 창)
vue<detail-button :row="params.data" :types="['window']" route-name="banner-detail" // routes.ts에 정의된 라우트명 back-to="/content/banner" // 닫기 버튼 클릭 시 돌아갈 경로 />Tab 타입 (새 탭)
vue<detail-button :row="params.data" :types="['tab']" route-name="banner-detail" // routes.ts에 정의된 라우트명 back-to="/content/banner" // 닫기 버튼 클릭 시 돌아갈 경로 />
Window/Tab 타입은 라우터 설정이 필요합니다:
{
path: 'banner/:id',
name: 'banner-detail',
// ⚠️ props.componentName 이 빠지면 탭/새창에서 빈 화면이 뜬다
props: route => ({id: route.params.id, componentName: 'banner/banner-detail'}),
component: () => import('src/views/common-detail.panel.vue'),
meta: {
hidden: true,
title: '배너 상세',
componentName: 'common-detail.panel' // ← 위와 이름만 같고 뜻이 다르다
}
}componentName 이 두 군데 나오는데 뜻이 다릅니다
| 위치 | 값 | 뜻 |
|---|---|---|
props.componentName | 'banner/banner-detail' | 상세 컴포넌트 경로. src/views/ 를 뗀 경로이며 디렉터리를 포함합니다 |
meta.componentName | 'common-detail.panel' | 호스트 화면 식별자. 항상 이 값 고정 |
props.componentName 은 src/views/**/*-detail.vue 를 모아 만든 레지스트리에서 정확히 일치해야 합니다. 경로가 틀리면 상세 화면이 열리지 않고, 개발자 콘솔에 등록된 경로 목록이 함께 출력됩니다.
예: src/views/message/target/msg-target-group-detail.vue → 'message/target/msg-target-group-detail' (views/ 접두어 ❌, 중간 디렉터리 생략 ❌)
💡 여러 타입을 동시에 지원할 수 있습니다:
<detail-button
:types="['popup', 'window', 'tab']" // 사용자가 선택 가능
/>:::