@vmscloud/moz-ui-grid-vue 0.2.8 → 0.2.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/MozGrid.vue.d.ts +2 -0
- package/dist/compat/MozGridVue.vue.d.ts +16 -2
- package/dist/compat/MozPivotVue.vue.d.ts +16 -2
- package/dist/composables/useGridPreset.d.ts +17 -3
- package/dist/index.cjs +2 -2
- package/dist/index.js +145 -62
- package/dist/style.css +1 -1
- package/dist/templates/GroupTemplate.d.ts +8 -6
- package/docs/manual/examples.md +189 -9
- package/docs/manual/reference.md +475 -54
- package/docs/manual/reference_vue.md +316 -43
- package/package.json +2 -1
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* 그룹 헤더 커스터마이징을 위한 렌더리스 컴포넌트.
|
|
3
3
|
*
|
|
4
|
+
* 슬롯은 **보이는 그룹 배너** 안에 마운트되어 배너의 라벨·건수·집계 자리를 대체한다(펼침/접힘 토글
|
|
5
|
+
* 버튼은 core 가 유지한다). 배너 본문 클릭은 그룹 토글로 위임되고, 슬롯 요소의 이벤트(툴팁 등)는
|
|
6
|
+
* 슬롯이 그대로 받는다. 배너가 생기지 않는 컬럼 구성(가운데 컬럼이 모두 `unmergeOnGroupRow`)에서는
|
|
7
|
+
* 예전처럼 그룹행 요소에 마운트된다.
|
|
8
|
+
*
|
|
4
9
|
* @example
|
|
5
10
|
* ```vue
|
|
6
11
|
* <MozGridVue :fields="fields" :data="data">
|
|
7
|
-
* <GroupTemplate #default="{ groupKey, groupValue, count
|
|
8
|
-
* <
|
|
9
|
-
*
|
|
10
|
-
* <strong>{{ groupKey }}: {{ groupValue }}</strong>
|
|
11
|
-
* <span class="text-gray-500">({{ count }}건)</span>
|
|
12
|
-
* </div>
|
|
12
|
+
* <GroupTemplate #default="{ groupKey, groupValue, count }">
|
|
13
|
+
* <strong>{{ groupKey }}: {{ groupValue }}</strong>
|
|
14
|
+
* <span class="text-gray-500"> ({{ count }}건)</span>
|
|
13
15
|
* </GroupTemplate>
|
|
14
16
|
* </MozGridVue>
|
|
15
17
|
* ```
|
package/docs/manual/examples.md
CHANGED
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
## 목차
|
|
8
8
|
|
|
9
9
|
- [기본 플랫 그리드](#기본-플랫-그리드)
|
|
10
|
+
- [행 식별 정책과 자동 ID](#행-식별-정책과-자동-id)
|
|
11
|
+
- [숫자 제약과 날짜시간 편집기](#숫자-제약과-날짜시간-편집기)
|
|
10
12
|
- [grid.rows 사용 예제](#gridrows-사용-예제)
|
|
11
13
|
- [grid.columns 사용 예제](#gridcolumns-사용-예제)
|
|
12
14
|
- [grid.changes 사용 예제](#gridchanges-사용-예제)
|
|
@@ -47,6 +49,7 @@
|
|
|
47
49
|
```typescript
|
|
48
50
|
const grid = new PureSheet(container, {
|
|
49
51
|
mode: 'flat',
|
|
52
|
+
enableReferCache: true, // keyFields 생략: 내부 자동 ID 사용
|
|
50
53
|
fields: [
|
|
51
54
|
// id = 컬럼 **식별자**(가리킬 때: 정렬/필터 상태, 폭, 저장 레이아웃).
|
|
52
55
|
// field = 원본 데이터 **키**(읽을 때: row[field]). 생략하면 id 와 같은 값으로 정규화.
|
|
@@ -78,6 +81,104 @@ grid.destroy();
|
|
|
78
81
|
|
|
79
82
|
---
|
|
80
83
|
|
|
84
|
+
### 행 식별 정책과 자동 ID
|
|
85
|
+
|
|
86
|
+
`keyFields`의 암묵적 `['id']` 기본값은 없습니다. 원본에 `id` 속성이 있어도 업무 키로 쓰려면 `keyFields: ['id']`를 명시해야 합니다. 컬럼의 `FieldDef.id`는 컬럼 식별자이지 행 키 설정이 아닙니다.
|
|
87
|
+
|
|
88
|
+
| 설정 | 동작 |
|
|
89
|
+
|---|---|
|
|
90
|
+
| `keyFields: ['employeeNo']` | 명시한 업무 키로 식별. 잘못된 키를 자동 ID로 대체하지 않음 |
|
|
91
|
+
| `keyFields` 생략 + `enableReferCache: true` | 내부 자동 ID 사용. 업무 데이터에 합성 키 필드를 추가할 필요 없음 |
|
|
92
|
+
| `keyFields` 생략 + 캐시 생략/`false` | 초기화 오류. 키를 명시하거나 캐시를 켜야 함 |
|
|
93
|
+
| `keyFields: []` | 초기화 오류. 자동 ID를 원하면 속성 자체를 생략 |
|
|
94
|
+
|
|
95
|
+
명시적 업무 키는 캐시 없이 사용할 수 있지만, ID로 행 데이터를 찾는 API 등 참조 캐시가 필요한 경로는 `enableReferCache: true`를 설정해야 합니다. 대용량에서 캐시를 끈다면 업무 키를 명시하고 지원되는 sourceIndex 기반 API를 사용하세요.
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
// 업무 키가 있는 경우 — employeeNo는 실제 데이터 필드다.
|
|
99
|
+
const keyedGrid = new PureSheet(container, {
|
|
100
|
+
keyFields: ['employeeNo'],
|
|
101
|
+
enableReferCache: true,
|
|
102
|
+
fields: [{ id: 'name', dataType: 'string', header: '이름' }],
|
|
103
|
+
data: [{ employeeNo: 'E-001', name: '김민수' }],
|
|
104
|
+
});
|
|
105
|
+
await keyedGrid.waitForReady();
|
|
106
|
+
const employeeId = keyedGrid.rows.getByIndex(0).id;
|
|
107
|
+
await keyedGrid.changes.updateCellById(employeeId, 'name', '김민수 수정');
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
```typescript
|
|
111
|
+
// 업무 키가 없는 경우 — 같은 내용의 행도 서로 다른 행으로 식별한다.
|
|
112
|
+
const grid = new PureSheet(container, {
|
|
113
|
+
enableReferCache: true, // keyFields 생략: 자동 ID
|
|
114
|
+
fields: [
|
|
115
|
+
{ id: 'name', dataType: 'string', header: '이름' },
|
|
116
|
+
{ id: 'quantity', dataType: 'number', header: '수량' },
|
|
117
|
+
],
|
|
118
|
+
data: [{ name: '부품', quantity: 1 }, { name: '부품', quantity: 1 }],
|
|
119
|
+
editable: true,
|
|
120
|
+
rowSelection: { mode: 'multi' },
|
|
121
|
+
});
|
|
122
|
+
await grid.waitForReady();
|
|
123
|
+
|
|
124
|
+
// 원본 객체의 id나 내부 문자열 형식을 추측하지 않고 공개 API의 반환 ID를 사용한다.
|
|
125
|
+
const rowId = grid.rows.getByIndex(1).id;
|
|
126
|
+
grid.rows.selectRowsByIds([rowId]);
|
|
127
|
+
await grid.changes.updateCellById(rowId, 'quantity', 2);
|
|
128
|
+
console.log(grid.rows.getById(rowId).data);
|
|
129
|
+
|
|
130
|
+
const addedId = await grid.changes.addRow({ name: '신규 부품', quantity: 1 });
|
|
131
|
+
await grid.changes.updateCellById(addedId, 'quantity', 3);
|
|
132
|
+
await grid.changes.commit();
|
|
133
|
+
// commit 후에도 반환 ID로 같은 행을 조작한다.
|
|
134
|
+
await grid.changes.deleteRowById(addedId);
|
|
135
|
+
await grid.changes.undeleteRowById(addedId);
|
|
136
|
+
console.log(grid.rows.getById(addedId).data);
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
자동 ID는 현재 데이터 수명 안에서 재사용하는 식별자입니다. 정렬·필터·편집·commit·Undo/Redo에 사용하되, `loadData()`로 전체 데이터를 교체한 뒤에는 공개 API에서 다시 얻으세요. 서버의 영속 업무 키나 다음 로드의 ID로 저장하지 마세요. 행 객체 API에는 그리드가 반환한 객체를 사용하고, 동일한 값을 가진 새 객체를 만들어 같은 행이라고 가정하지 마세요.
|
|
140
|
+
|
|
141
|
+
> 아래 API 목록의 `'row-1'`, `'user-5'`, `1` 등은 **실제로 얻은 rowId를 대신 적은 예시 값**입니다. 자동 ID 모드에서는 반환 ID로 바꿔 사용하세요. 업무 키가 필요한 트리 관계나 Excel upsert/충돌 매칭은 별도로 명시적 키를 구성해야 합니다. 신규 행의 업무 키를 생략한 CRUD 예제는 자동 ID 모드를 전제로 합니다.
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
### 숫자 제약과 날짜시간 편집기
|
|
146
|
+
|
|
147
|
+
`id`는 컬럼 식별자, `field`는 원본 데이터 키, `dataType`은 데이터 타입, `editor`는 편집 UI 설정입니다. 날짜시간도 `dataType: 'date'`를 쓰며 `datetime`은 **editor 타입**입니다.
|
|
148
|
+
|
|
149
|
+
```typescript
|
|
150
|
+
import { PureSheet, type FieldDef } from '@vmscloud/moz-ui-grid-core';
|
|
151
|
+
|
|
152
|
+
const fields: FieldDef[] = [
|
|
153
|
+
{
|
|
154
|
+
id: 'quantity', field: 'quantity', header: '수량', dataType: 'number',
|
|
155
|
+
editor: { type: 'number', min: 0, max: 100, step: 0.5 },
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
id: 'scheduledAt', field: 'scheduledAt', header: '예약 시각', dataType: 'date',
|
|
159
|
+
editor: { type: 'datetime' },
|
|
160
|
+
mask: { type: 'date', pattern: 'YYYY-MM-DD HH:mm:ss' },
|
|
161
|
+
},
|
|
162
|
+
];
|
|
163
|
+
const grid = new PureSheet(container, {
|
|
164
|
+
fields,
|
|
165
|
+
enableReferCache: true,
|
|
166
|
+
editable: true,
|
|
167
|
+
timeZone: 'Asia/Seoul',
|
|
168
|
+
data: [
|
|
169
|
+
{ quantity: 1.5, scheduledAt: new Date('2026-10-19T00:30:00Z') },
|
|
170
|
+
{ quantity: 0, scheduledAt: null },
|
|
171
|
+
],
|
|
172
|
+
});
|
|
173
|
+
await grid.waitForReady();
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
- 숫자의 `min`/`max`는 경계를 포함하며, `step`은 `min`(생략 시 0)을 기준으로 하는 양수 간격입니다. 생략한 제약은 적용되지 않습니다. 범위/간격을 벗어난 입력은 에디터 커밋에서 오류로 표시되며 자동으로 잘라내거나 반올림하지 않습니다. 빈 입력은 `null`입니다. 이 옵션을 모든 프로그램적 mutation의 검증 규칙으로 간주하지 마세요.
|
|
177
|
+
- `datetime`은 `datetime-local` 입력을 사용하지만 커밋 값은 HTML 문자열이 아닌 **`Date | null`**입니다. 위 예제의 최초 표시/편집 시각은 서울 기준 `2026-10-19 09:30:00`이며, 시간대 설정을 생략하면 브라우저 로컬 시간대를 사용합니다. 서버에서 받은 ISO 문자열을 이 계약으로 쓰려면 데이터 준비 단계에서 `Date`로 변환하세요.
|
|
178
|
+
- 기존 `editor: { type: 'date' }`는 날짜 전용 입력과 **문자열 커밋** 동작을 유지합니다. `editor: { type: 'datepicker', dateFormat: 'yyyy-MM-dd' }`의 `dateFormat`도 유지됩니다. 이는 아래 XLSX export에서 제거된 옵션과 별개이며, `mask.pattern`의 `YYYY-MM-DD` 토큰과 혼동하지 마세요.
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
81
182
|
### grid.rows 사용 예제
|
|
82
183
|
|
|
83
184
|
```typescript
|
|
@@ -174,15 +275,20 @@ const deletedCount = await grid.rows.deleteSelectedRows();
|
|
|
174
275
|
const updatedCount = await grid.rows.updateSelectedRows('status', 'approved');
|
|
175
276
|
const discardedCount = await grid.rows.discardSelectedRows();
|
|
176
277
|
|
|
177
|
-
// ── 데이터 행 고정 ──
|
|
178
|
-
grid.rows.pinTopById('row-1'); // ID로 기존 행을 상단 고정
|
|
179
|
-
grid.rows.pinTopByIndex(0); // sourceIndex로 기존 행을 상단 고정
|
|
180
|
-
grid.rows.pinBottomById('row-2'); // ID로 기존 행을 하단 고정
|
|
181
|
-
grid.rows.pinBottomByIndex(1); // sourceIndex로 기존 행을 하단 고정
|
|
278
|
+
// ── 데이터 행 고정 (본문 행을 고정 영역으로 옮김 — setProps({ pinned })와 동일, 본문에서는 빠짐) ──
|
|
279
|
+
grid.rows.pinTopById('row-1'); // ID로 기존 행을 상단 고정 영역으로 옮김
|
|
280
|
+
grid.rows.pinTopByIndex(0); // sourceIndex로 기존 행을 상단 고정 영역으로 옮김
|
|
281
|
+
grid.rows.pinBottomById('row-2'); // ID로 기존 행을 하단 고정 영역으로 옮김
|
|
282
|
+
grid.rows.pinBottomByIndex(1); // sourceIndex로 기존 행을 하단 고정 영역으로 옮김
|
|
283
|
+
grid.rows.unpinById('row-1'); // 본문 원래 위치로 복귀
|
|
182
284
|
|
|
183
|
-
// ── 구조적 행 고정 ──
|
|
184
|
-
const pinnedRow = grid.rows.addPinnedTop({
|
|
185
|
-
|
|
285
|
+
// ── 구조적 행 고정 (RowConfig: 데이터는 data 안에 지정) ──
|
|
286
|
+
const pinnedRow = grid.rows.addPinnedTop({
|
|
287
|
+
id: 'summary', structural: true, data: { label: '요약', amount: 9999 },
|
|
288
|
+
});
|
|
289
|
+
grid.rows.addPinnedBottom({
|
|
290
|
+
id: 'footer', structural: true, data: { label: '합계' },
|
|
291
|
+
});
|
|
186
292
|
|
|
187
293
|
// ── 고정 관리 ──
|
|
188
294
|
grid.rows.unpinById('summary');
|
|
@@ -464,6 +570,8 @@ grid.on('rowGroup:checkbox', (e) => console.log(e.groupId, e.checked, e.memberCo
|
|
|
464
570
|
|
|
465
571
|
### grid.tree 사용 예제
|
|
466
572
|
|
|
573
|
+
아래 관계/노드 ID 예제는 생성 시 `keyFields: ['id']`, `enableReferCache: true`를 설정하고 실제 `id`/`parentId` 데이터를 로드한 그리드를 전제로 합니다. `treeConfig.idField`만 지정한다고 행 업무 키의 암묵적 기본값이 복원되지는 않습니다.
|
|
574
|
+
|
|
467
575
|
```typescript
|
|
468
576
|
// ── 트리 설정 (flat 구조 — parentId 기반) ──
|
|
469
577
|
await grid.tree.setConfig({
|
|
@@ -548,6 +656,8 @@ const config = grid.tree.getConfig();
|
|
|
548
656
|
```typescript
|
|
549
657
|
// ── 트리 드래그 reorder 활성화 (treeConfig + reorderableRows) ──
|
|
550
658
|
const grid = new PureSheet(container, {
|
|
659
|
+
keyFields: ['id'], // 트리 관계에 쓰는 업무 키를 명시
|
|
660
|
+
enableReferCache: true,
|
|
551
661
|
treeConfig: { idField: 'id', parentField: 'parentId', treeColumn: 'name' },
|
|
552
662
|
dragDropConfig: {
|
|
553
663
|
reorderableRows: true, // treeConfig와 함께 → 트리 인식 드래그 자동 활성
|
|
@@ -705,7 +815,7 @@ const series = await grid.pivot.getSeriesData(); // 차트용 시리즈
|
|
|
705
815
|
await grid.masterDetail.setConfig({
|
|
706
816
|
expandColumn: 'name',
|
|
707
817
|
singleExpand: false,
|
|
708
|
-
keepExpandedOnDataChange: false
|
|
818
|
+
keepExpandedOnDataChange: true, // 기본값 — 정렬·필터·재조회(같은 keyFields 키) 뒤에도 펼친 채 유지. false 면 모두 접힘
|
|
709
819
|
keepMasterDetailRows: true,
|
|
710
820
|
keepMasterDetailRowsCount: 10,
|
|
711
821
|
minHeight: 100,
|
|
@@ -888,6 +998,63 @@ grid.headers.expandAtLevel(0); // level 0 그룹만 펼치기
|
|
|
888
998
|
|
|
889
999
|
### grid.io 사용 예제
|
|
890
1000
|
|
|
1001
|
+
업무 키로 기존 행을 매칭하는 import 예제(`upsert`, append 충돌 처리 등)는 생성 시 `keyFields`를 명시한 그리드를 사용하세요. 자동 ID는 Excel 파일에 담긴 업무 키가 아니므로 재가져오기에서 같은 행을 식별하는 키로 간주하면 안 됩니다.
|
|
1002
|
+
|
|
1003
|
+
#### 컬럼별 XLSX 날짜 서식과 구조적 고정 행
|
|
1004
|
+
|
|
1005
|
+
공개 `toExcel`/`saveExcelToFile` 옵션의 `dateFormat`은 제거되었습니다. 날짜 표시를 보존하려면 각 `dataType: 'date'` 필드에 구조화된 `mask`를 지정하고 `preserveFormatting: true`를 사용하세요. 날짜 편집기의 `dateFormat`과는 별개입니다.
|
|
1006
|
+
|
|
1007
|
+
```typescript
|
|
1008
|
+
import { PureSheet, type FieldDef } from '@vmscloud/moz-ui-grid-core';
|
|
1009
|
+
|
|
1010
|
+
const fields: FieldDef[] = [
|
|
1011
|
+
{ id: 'name', header: '항목', dataType: 'string' },
|
|
1012
|
+
{
|
|
1013
|
+
id: 'day', header: '기준일', dataType: 'date',
|
|
1014
|
+
mask: { type: 'date', pattern: 'YYYY-MM-DD' },
|
|
1015
|
+
},
|
|
1016
|
+
{
|
|
1017
|
+
id: 'recordedAt', header: '기록 시각', dataType: 'date',
|
|
1018
|
+
mask: { type: 'date', pattern: 'YYYY-MM-DD HH:mm:ss' },
|
|
1019
|
+
},
|
|
1020
|
+
];
|
|
1021
|
+
const grid = new PureSheet(container, {
|
|
1022
|
+
fields,
|
|
1023
|
+
enableReferCache: true,
|
|
1024
|
+
timeZone: 'Asia/Seoul',
|
|
1025
|
+
data: [{
|
|
1026
|
+
name: '입고',
|
|
1027
|
+
day: new Date('2026-10-19T00:00:00+09:00'),
|
|
1028
|
+
recordedAt: new Date('2026-10-19T09:30:45+09:00'),
|
|
1029
|
+
}],
|
|
1030
|
+
});
|
|
1031
|
+
await grid.waitForReady();
|
|
1032
|
+
grid.rows.addPinnedTop({
|
|
1033
|
+
id: 'export-note', structural: true, data: { name: '서울 기준 입고 내역' },
|
|
1034
|
+
});
|
|
1035
|
+
|
|
1036
|
+
const blob = await grid.io.toExcel({
|
|
1037
|
+
scope: 'all',
|
|
1038
|
+
preserveFormatting: true,
|
|
1039
|
+
structuralPinnedRows: 'include',
|
|
1040
|
+
});
|
|
1041
|
+
// day → yyyy-mm-dd, recordedAt → yyyy-mm-dd hh:mm:ss (Excel numFmt).
|
|
1042
|
+
// blob 다운로드는 아래 기본 export 예제와 동일하다.
|
|
1043
|
+
|
|
1044
|
+
// 직접 파일 저장도 같은 컬럼별 서식/고정 행 옵션을 사용한다.
|
|
1045
|
+
await grid.io.saveExcelToFile({
|
|
1046
|
+
suggestedName: 'receipts.xlsx',
|
|
1047
|
+
preserveFormatting: true,
|
|
1048
|
+
structuralPinnedRows: 'include',
|
|
1049
|
+
});
|
|
1050
|
+
```
|
|
1051
|
+
|
|
1052
|
+
- `preserveFormatting` 기본값은 `false`입니다. 생략/`false`, 날짜 mask 없음 또는 지원하지 않는 날짜 mask는 기본 Excel 날짜 서식 `yyyy-mm-dd`를 사용합니다. 지원 불가 패턴은 `PS005` 경고를 냅니다. 표시 서식은 날짜 값의 시간 정보를 잘라내는 옵션이 아닙니다.
|
|
1053
|
+
- `structuralPinnedRows` 기본값은 `'exclude'`입니다. `'include'`는 **상단 고정 → 본문 → 하단 고정** 순서로 구조적 행의 현재 typed 집계값과 원시 라벨 데이터를 내보냅니다. `scope: 'selected'`에서는 선택된 고정 행만 포함합니다.
|
|
1054
|
+
- 이 옵션은 원본(`exportSource: true`)·피벗 export 및 CSV에는 적용되지 않습니다. DOM/`formatRow` 결과나 집계 formatter가 만든 화면 문자열을 직렬화하는 옵션도 아닙니다.
|
|
1055
|
+
|
|
1056
|
+
#### 기타 IO 작업
|
|
1057
|
+
|
|
891
1058
|
```typescript
|
|
892
1059
|
// ── 1) 기본 export (메모리 Blob) ──
|
|
893
1060
|
const blob = await grid.io.toExcel({
|
|
@@ -1722,6 +1889,7 @@ import {
|
|
|
1722
1889
|
} from '@vmscloud/moz-ui-grid-core';
|
|
1723
1890
|
|
|
1724
1891
|
const grid = new PureSheet(el, {
|
|
1892
|
+
enableReferCache: true, // keyFields 생략: 내부 자동 ID 사용
|
|
1725
1893
|
fields,
|
|
1726
1894
|
// 옛 저장본을 현재 스키마로 올린다. core 는 호출 시점·순서만 책임지고,
|
|
1727
1895
|
// 어떤 버전에서 무엇을 바꿀지는 스키마를 아는 소비처가 정한다.
|
|
@@ -1781,17 +1949,20 @@ moz-ui-grid-core는 행 선택과 셀 선택을 **독립된 두 옵션**(`rowSel
|
|
|
1781
1949
|
```typescript
|
|
1782
1950
|
// ── 행 전용 (단순 list 그리드) ──
|
|
1783
1951
|
new PureSheet(container, {
|
|
1952
|
+
enableReferCache: true, // keyFields 생략: 내부 자동 ID 사용
|
|
1784
1953
|
rowSelection: { mode: 'multi' },
|
|
1785
1954
|
});
|
|
1786
1955
|
// trigger 미지정 → 자동 'cellClick' (셀 클릭으로 행 선택)
|
|
1787
1956
|
|
|
1788
1957
|
// ── 셀 전용 (Excel 스타일) ──
|
|
1789
1958
|
new PureSheet(container, {
|
|
1959
|
+
enableReferCache: true, // keyFields 생략: 내부 자동 ID 사용
|
|
1790
1960
|
cellSelection: { mode: 'range' },
|
|
1791
1961
|
});
|
|
1792
1962
|
|
|
1793
1963
|
// ── 셀+행 분리: 행 헤더 클릭으로 행 선택 (정합성 보호) ──
|
|
1794
1964
|
new PureSheet(container, {
|
|
1965
|
+
enableReferCache: true, // keyFields 생략: 내부 자동 ID 사용
|
|
1795
1966
|
rowSelection: { mode: 'multi' }, // trigger 자동 = 'rowHeader'
|
|
1796
1967
|
cellSelection: { mode: 'range' },
|
|
1797
1968
|
});
|
|
@@ -1799,18 +1970,21 @@ new PureSheet(container, {
|
|
|
1799
1970
|
|
|
1800
1971
|
// ── 체크박스 트리거 ──
|
|
1801
1972
|
new PureSheet(container, {
|
|
1973
|
+
enableReferCache: true, // keyFields 생략: 내부 자동 ID 사용
|
|
1802
1974
|
rowSelection: { mode: 'multi', trigger: 'checkbox' },
|
|
1803
1975
|
});
|
|
1804
1976
|
// _rowHeader 컬럼 자동 주입 + CSS-only 체크박스 자동 렌더.
|
|
1805
1977
|
|
|
1806
1978
|
// ── 트리거 복수 지정 (행 헤더 + 체크박스) ──
|
|
1807
1979
|
new PureSheet(container, {
|
|
1980
|
+
enableReferCache: true, // keyFields 생략: 내부 자동 ID 사용
|
|
1808
1981
|
rowSelection: { mode: 'multi', trigger: ['rowHeader', 'checkbox'] },
|
|
1809
1982
|
cellSelection: { mode: 'range' },
|
|
1810
1983
|
});
|
|
1811
1984
|
|
|
1812
1985
|
// ── 셀 클릭이 행도 선택 (legacy 'all' 동작) ──
|
|
1813
1986
|
new PureSheet(container, {
|
|
1987
|
+
enableReferCache: true, // keyFields 생략: 내부 자동 ID 사용
|
|
1814
1988
|
rowSelection: { mode: 'multi', trigger: 'cellClick' }, // 명시 지정
|
|
1815
1989
|
cellSelection: { mode: 'range' },
|
|
1816
1990
|
});
|
|
@@ -1839,6 +2013,7 @@ AG Grid의 `ctrlASelectsRows` 옵션과 같은 의미.
|
|
|
1839
2013
|
```typescript
|
|
1840
2014
|
// 기본 — 셀만 전체 선택 (AG Grid와 동일)
|
|
1841
2015
|
new PureSheet(container, {
|
|
2016
|
+
enableReferCache: true, // keyFields 생략: 내부 자동 ID 사용
|
|
1842
2017
|
rowSelection: { mode: 'multi' },
|
|
1843
2018
|
cellSelection: { mode: 'range' },
|
|
1844
2019
|
// rowSelection.includeInSelectAll: false (기본)
|
|
@@ -1846,6 +2021,7 @@ new PureSheet(container, {
|
|
|
1846
2021
|
|
|
1847
2022
|
// Ctrl+A로 행도 함께 fill
|
|
1848
2023
|
new PureSheet(container, {
|
|
2024
|
+
enableReferCache: true, // keyFields 생략: 내부 자동 ID 사용
|
|
1849
2025
|
rowSelection: { mode: 'multi', includeInSelectAll: true },
|
|
1850
2026
|
cellSelection: { mode: 'range' },
|
|
1851
2027
|
});
|
|
@@ -1865,6 +2041,7 @@ new PureSheet(container, {
|
|
|
1865
2041
|
```typescript
|
|
1866
2042
|
// 기본 (Policy A — 엄격 분리)
|
|
1867
2043
|
new PureSheet(container, {
|
|
2044
|
+
enableReferCache: true, // keyFields 생략: 내부 자동 ID 사용
|
|
1868
2045
|
rowSelection: { mode: 'multi' },
|
|
1869
2046
|
cellSelection: { mode: 'range' },
|
|
1870
2047
|
// cellSelectionImpliesRows: false (기본)
|
|
@@ -1873,6 +2050,7 @@ new PureSheet(container, {
|
|
|
1873
2050
|
|
|
1874
2051
|
// Policy B — Excel/Google Sheets 동작
|
|
1875
2052
|
new PureSheet(container, {
|
|
2053
|
+
enableReferCache: true, // keyFields 생략: 내부 자동 ID 사용
|
|
1876
2054
|
rowSelection: { mode: 'multi' },
|
|
1877
2055
|
cellSelection: { mode: 'range' },
|
|
1878
2056
|
cellSelectionImpliesRows: true,
|
|
@@ -2132,6 +2310,7 @@ const chartField = {
|
|
|
2132
2310
|
|
|
2133
2311
|
```typescript
|
|
2134
2312
|
new PureSheet(el, {
|
|
2313
|
+
enableReferCache: true, // keyFields 생략: 내부 자동 ID 사용
|
|
2135
2314
|
fields,
|
|
2136
2315
|
rowSelection: { mode: 'multi', trigger: 'checkbox' },
|
|
2137
2316
|
rowHeader: {
|
|
@@ -2201,6 +2380,7 @@ grid.formatRow.removeHandler('highlight');
|
|
|
2201
2380
|
|
|
2202
2381
|
```typescript
|
|
2203
2382
|
new PureSheet(el, {
|
|
2383
|
+
enableReferCache: true, // keyFields 생략: 내부 자동 ID 사용
|
|
2204
2384
|
fields,
|
|
2205
2385
|
formatHeader: (ctx) => {
|
|
2206
2386
|
// 정렬된 컬럼에 data-* 마커
|