페이지네이션 per_page 선택값 브라우저 복원 문제 수정

- pagination.blade.php: data-server-value 속성 추가, 즉시 실행 스크립트로 서버값 강제 설정
- pagination.js: htmx:afterSwap에서 쿠키값 대신 서버값(data-server-value) 우선 사용
- item-fields: 페이지네이션 추가, handlePageChange/handlePerPageChange 핸들러 구현
- 디버그 코드 제거
This commit is contained in:
2025-12-16 23:16:50 +09:00
parent 9f00585401
commit 15a2cff453
4 changed files with 129 additions and 11 deletions

View File

@@ -114,8 +114,13 @@ document.body.addEventListener('htmx:afterSwap', function(event) {
setTimeout(function() {
const perPageSelect = document.getElementById('perPageSelect');
if (perPageSelect) {
const savedPerPage = getPerPageFromCookie();
perPageSelect.value = savedPerPage;
// 서버에서 받은 값(data-server-value)을 우선 사용
const serverValue = perPageSelect.dataset.serverValue;
if (serverValue) {
perPageSelect.value = serverValue;
// 쿠키도 서버 값으로 업데이트
setCookie('pagination_per_page', serverValue);
}
}
}, 50);
});

View File

@@ -1065,6 +1065,54 @@ function switchTab(tab) {
htmx.trigger('#custom-fields', 'customRefresh');
});
// 페이지 변경 핸들러 (pagination 컴포넌트에서 호출)
window.handlePageChange = function(page) {
const form = document.getElementById('customFilterForm');
if (form) {
// hidden input으로 page 값 설정
let pageInput = form.querySelector('input[name="page"]');
if (!pageInput) {
pageInput = document.createElement('input');
pageInput.type = 'hidden';
pageInput.name = 'page';
form.appendChild(pageInput);
}
pageInput.value = page;
// customRefresh 이벤트 트리거
htmx.trigger('#custom-fields', 'customRefresh');
}
};
// 페이지당 항목 수 변경 핸들러 (pagination 컴포넌트에서 호출)
window.handlePerPageChange = function(perPage) {
const form = document.getElementById('customFilterForm');
if (form) {
// hidden input으로 per_page 값 설정
let perPageInput = form.querySelector('input[name="per_page"]');
if (!perPageInput) {
perPageInput = document.createElement('input');
perPageInput.type = 'hidden';
perPageInput.name = 'per_page';
form.appendChild(perPageInput);
}
perPageInput.value = perPage;
// 페이지는 1로 리셋
let pageInput = form.querySelector('input[name="page"]');
if (!pageInput) {
pageInput = document.createElement('input');
pageInput.type = 'hidden';
pageInput.name = 'page';
form.appendChild(pageInput);
}
pageInput.value = 1;
// customRefresh 이벤트 트리거
htmx.trigger('#custom-fields', 'customRefresh');
}
};
// 시딩 새로고침
function refreshSeeding() {
htmx.trigger('#seeding-status', 'seedingRefresh');

View File

@@ -348,14 +348,15 @@ class="text-red-600 hover:text-red-800 p-1" title="삭제">
<div class="px-4 py-3 bg-gray-50 border-t border-gray-200">
<div class="flex flex-wrap items-center justify-between gap-2 text-sm text-gray-600">
<div class="flex items-center gap-4">
<span> {{ $fields->count() }}</span>
@php
$systemCount = $fields->filter(fn($f) => $f->is_common || $f->storage_type === 'column')->count();
$customCount = $fields->count() - $systemCount;
$activeCount = $fields->filter(fn($f) => $f->is_active)->count();
$lockedCount = $fields->filter(fn($f) => $f->is_locked)->count();
$withOptionsCount = $fields->filter(fn($f) => !empty($f->options))->count();
$deletedCount = $fields->filter(fn($f) => !is_null($f->deleted_at))->count();
// 현재 페이지의 항목으로 통계 계산
$currentItems = $fields->getCollection();
$systemCount = $currentItems->filter(fn($f) => $f->is_common || $f->storage_type === 'column')->count();
$customCount = $currentItems->count() - $systemCount;
$activeCount = $currentItems->filter(fn($f) => $f->is_active)->count();
$lockedCount = $currentItems->filter(fn($f) => $f->is_locked)->count();
$withOptionsCount = $currentItems->filter(fn($f) => !empty($f->options))->count();
$deletedCount = $currentItems->filter(fn($f) => !is_null($f->deleted_at))->count();
@endphp
<span class="text-blue-600">시스템: {{ $systemCount }}</span>
<span class="text-green-600">커스텀: {{ $customCount }}</span>
@@ -364,8 +365,8 @@ class="text-red-600 hover:text-red-800 p-1" title="삭제">
@if($deletedCount > 0)
<span class="text-red-500">삭제됨: {{ $deletedCount }}</span>
@endif
@if($activeCount < $fields->count())
<span class="text-gray-500">비활성: {{ $fields->count() - $activeCount }}</span>
@if($activeCount < $currentItems->count())
<span class="text-gray-500">비활성: {{ $currentItems->count() - $activeCount }}</span>
@endif
@if($lockedCount > 0)
<span class="text-orange-500">잠금: {{ $lockedCount }}</span>
@@ -377,6 +378,13 @@ class="text-red-600 hover:text-red-800 p-1" title="삭제">
</div>
</div>
<!-- 페이지네이션 -->
@include('partials.pagination', [
'paginator' => $fields,
'target' => '#custom-fields',
'includeForm' => '#customFilterForm'
])
<script>
function toggleAccordion(fieldId) {
const accordion = document.getElementById('accordion-' + fieldId);
@@ -529,5 +537,53 @@ function forceDeleteCustomField(fieldId, fieldName) {
});
});
}
// 페이지 변경 핸들러
function handlePageChange(page) {
const form = document.getElementById('customFilterForm');
if (form) {
// hidden input으로 page 값 설정
let pageInput = form.querySelector('input[name="page"]');
if (!pageInput) {
pageInput = document.createElement('input');
pageInput.type = 'hidden';
pageInput.name = 'page';
form.appendChild(pageInput);
}
pageInput.value = page;
// customRefresh 이벤트 트리거 (hx-trigger="customRefresh from:body" 에 맞춤)
htmx.trigger('#custom-fields', 'customRefresh');
}
}
// 페이지당 항목 수 변경 핸들러
function handlePerPageChange(perPage) {
const form = document.getElementById('customFilterForm');
if (form) {
// hidden input으로 per_page 값 설정
let perPageInput = form.querySelector('input[name="per_page"]');
if (!perPageInput) {
perPageInput = document.createElement('input');
perPageInput.type = 'hidden';
perPageInput.name = 'per_page';
form.appendChild(perPageInput);
}
perPageInput.value = perPage;
// 페이지는 1로 리셋
let pageInput = form.querySelector('input[name="page"]');
if (!pageInput) {
pageInput = document.createElement('input');
pageInput.type = 'hidden';
pageInput.name = 'page';
form.appendChild(pageInput);
}
pageInput.value = 1;
// customRefresh 이벤트 트리거 (hx-trigger="customRefresh from:body" 에 맞춤)
htmx.trigger('#custom-fields', 'customRefresh');
}
}
</script>
@endif

View File

@@ -51,6 +51,8 @@ class="ml-3 relative inline-flex items-center px-4 py-2 border border-gray-300 t
<select name="per_page" id="perPageSelect"
style="min-width: 90px;"
class="px-3 py-1 border border-gray-300 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-blue-500"
autocomplete="off"
data-server-value="{{ $paginator->perPage() }}"
onchange="handlePerPageChange(this.value)">
<option value="10" {{ $paginator->perPage() == 10 ? 'selected' : '' }}>10개씩</option>
<option value="20" {{ $paginator->perPage() == 20 ? 'selected' : '' }}>20개씩</option>
@@ -60,6 +62,13 @@ class="px-3 py-1 border border-gray-300 rounded-lg text-sm focus:outline-none fo
<option value="200" {{ $paginator->perPage() == 200 ? 'selected' : '' }}>200개씩</option>
<option value="500" {{ $paginator->perPage() == 500 ? 'selected' : '' }}>500개씩</option>
</select>
{{-- 브라우저 form restoration 방지: 서버 값으로 강제 설정 --}}
<script>
(function() {
var s = document.getElementById('perPageSelect');
if (s && s.dataset.serverValue) s.value = s.dataset.serverValue;
})();
</script>
</div>
<div>
<nav class="relative z-0 inline-flex rounded-md shadow-sm -space-x-px" aria-label="Pagination">