푸들푸들

[Error] 탭 변경 시 CSS 깨짐 본문

구디아카데미/Error

[Error] 탭 변경 시 CSS 깨짐

COCO_develop 2025. 1. 14. 23:08

저번 글과 이어서..

<div class="simple-tab">
    <!-- 탭 title -->
    <ul class="nav nav-tabs d-flex justify-content-between" id="pills-tab" role="tablist">
        <div class="d-flex">
            <li class="nav-item" role="presentation">
                <button class="nav-link active" id="전체-tab" data-bs-toggle="tab" data-bs-target="#전체-tab-pane" type="button" role="tab" aria-controls="#전체-tab-pane" aria-selected="true">전체</button>
            </li>
            <c:forEach var="ct" items="${categoryList}">
                <li class="nav-item" role="presentation">
                    <button class="nav-link" id="tab${ct.catNo}" data-bs-toggle="tab" data-bs-target="#${ct.catName}-tab-pane" type="button" role="tab" aria-controls="#${ct.catName}-tab-pane" aria-selected="false">${ct.catName}</button>
                </li>
            </c:forEach>
        </div>
        <span style="text-align: right;">
            <a class="btn btn-secondary" id="insertBoard" href="${pageContext.request.contextPath}/board/insert">
                <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-plus">
                <line x1="12" y1="5" x2="12" y2="19"></line><line x1="5" y1="12" x2="19" y2="12"></line></svg> 글쓰기
            </a>
        </span>
    </ul>
    <!-- END 탭 title -->

    <div class="tab-content" id="tabContent">
        <!-- 탭1 - 전체 -->
        <div class="tab-pane fade show active" id="전체-tab-pane" role="tabpanel" aria-labelledby="전체-tab" tabindex="0">
            <div class="widget-content widget-content-area br-8">

                <table id="board-list" class="table dt-table-hover" style="width:100%">
                    <thead>
                        <tr>
                            <th style="text-align: center;">번호</th>
                            <th>제목</th>
                            <th>작성자</th>
                            <th>작성일</th>
                            <th style="text-align: center;">조회수</th>
                            <th style="text-align: center;">추천</th>
                        </tr>
                    </thead>
                    <tbody>
                        <c:forEach var="b" items="${boardList}">
                            <tr>
                                <td style="text-align: center;">${b.boaNo}</td>
                                <td>
                                    <div class="d-flex justify-content-left align-items-center">
                                        <div class="d-flex flex-column">
                                            <span class="text-truncate fw-bold">
                                                [${b.catName}] <a href="${pageContext.request.contextPath}/board/${b.boaNo}">${b.title}</a>
                                            </span>
                                        </div>
                                    </div>
                                </td>
                                <td>${b.ename}</td>
                                <td>${b.createDate}</td>
                                <td style="text-align: center;">${b.viewCnt}</td>
                                <td style="text-align: center;">${b.countLike}</td>
                            </tr>
                        </c:forEach>
                    </tbody>
                </table>
            </div>
        </div>
        <!-- END 탭1 - 전체 -->

        <!-- 탭2 - 인기글 --> <!-- 추천수 10개 이상 -->

        <!-- 탭3 ~ -->
        <c:forEach var="ct" items="${categoryList}">
            <c:if test="${ct.catNo != 1}"> <!-- 공지(catNo=1) 제외 -->
                <div class="tab-pane fade" id="${ct.catName}-tab-pane" role="tabpanel" aria-labelledby="tab${ct.catNo}" tabindex="0">

                    <div class="widget-content widget-content-area br-8">    
                        <table id="${ct.catName}-board-list" class="table dt-table-hover" style="width:100%">
                            <thead>
                                <tr>
                                    <th style="text-align: center;">번호</th>
                                    <th>제목</th>
                                    <th>작성자</th>
                                    <th>작성일</th>
                                    <th style="text-align: center;">조회수</th>
                                    <th style="text-align: center;">추천</th>
                                </tr>
                            </thead>
                            <tbody>
                                <!-- ajax -->
                            </tbody>
                        </table>
                    </div>
                 </div>
            </c:if>
         </c:forEach>
         <!-- END 탭 -->
    </div>
</div>

<script src="../src/plugins/src/table/datatable/datatables.js"></script>
<script>
    $('#board-list').DataTable({
        "dom": "<'dt--top-section'<'row'<'col-12 col-sm-6 d-flex justify-content-sm-start justify-content-center'l><'col-12 col-sm-6 d-flex justify-content-sm-end justify-content-center mt-sm-0 mt-3'f>>>" +
        "<'table-responsive'tr>" +
        "<'dt--bottom-section d-sm-flex justify-content-sm-between text-center'<'dt--pages-count  mb-sm-0 mb-3'i><'dt--pagination'p>>",
            "oLanguage": {
                "oPaginate": { "sPrevious": '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-arrow-left"><line x1="19" y1="12" x2="5" y2="12"></line><polyline points="12 19 5 12 12 5"></polyline></svg>', "sNext": '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-arrow-right"><line x1="5" y1="12" x2="19" y2="12"></line><polyline points="12 5 19 12 12 19"></polyline></svg>' },
                "sInfo": "Showing page _PAGE_ of _PAGES_",
                "sSearch": '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-search"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line></svg>',
                "sSearchPlaceholder": "Search...",
               "sLengthMenu": "Results :  _MENU_",
            },
            "stripeClasses": [],
            "lengthMenu": [7, 10, 20, 50],
            "pageLength": 10 
        });
</script>
<!-- END PAGE LEVEL SCRIPTS --> 

<script>
    $(document).ready(function() {
        // 기본적으로 전체 탭의 데이터를 로드
        tabData('전체');

        // 탭 클릭 이벤트
        $('#pills-tab button[data-bs-toggle="tab"]').click(function() {
            let buttonId = $(this).attr('id'); // 현재 클릭된 버튼의 ID
            let tabDataType;

            // tabDataType을 설정
            if (buttonId === '전체-tab') {
                tabDataType = '전체';
            } else {
                tabDataType = buttonId.replace('tab', ''); // tabDataType을 버튼 ID에서 'tab'을 제거한 값으로 설정
            }

            // 해당 탭의 데이터를 로드
            tabData(tabDataType);
        });

        function tabData(tabData) {
            let url; 
            if (tabData === '전체') {
                url = '/board';
            } else {
                let catNo = tabData.replace('tab', '').trim();
                console.log(catNo);
                url = `/board/byCategory/`+catNo; // 카테고리별 게시글을 가져오는 URL
                console.log(url);
            }

            fetch(url)
                .then(response => response.json())
                .then(data => {
                    let tbody;
                    if (tabData === '전체') {
                        tbody = $('#board-list tbody'); // 전체 탭의 tbody
                    } else {
                        tbody = $(`#${tabData}-board-list tbody`); // 카테고리 탭의 tbody
                    }

                    tbody.empty(); // 기존 데이터 초기화

                    data.forEach(item => {
                        console.log(item)
                        let row = $('<tr></tr>');
                        row.append($('<td></td>').text(item.boaNo));
                        row.append($('<td></td>').html(`[${item.catName}] <a href="/board/${item.boaNo}">${item.title}</a>`));
                        row.append($('<td></td>').text(item.ename));
                        row.append($('<td></td>').text(item.createDate));
                        row.append($('<td></td>').text(item.viewCnt));
                        row.append($('<td></td>').text(item.countLike));

                        tbody.append(row); // 새로운 행 추가
                    });
                })
                .catch(error => console.error('Error loading data:', error));
        }
    });
</script>

 

처음 화면인 '전체' 탭은 괜찮은데

다른 탭을 선택하면 css가 깨져서 나타남

 

-> 페이지네이션, 검색 등을 추가하는 부분을 탭이 바뀔 때마다 초기화 했다가 다시 추가하는 방식으로 구현해보자!

 

<div class="tab-content" id="tabContent">
    <!-- 탭1 - 전체 -->
    <div class="tab-pane fade show active" id="전체-tab-pane" role="tabpanel" aria-labelledby="tab-전제" tabindex="0">
        <div class="widget-content widget-content-area br-8">
            <table id="board-list" class="table dt-table-hover zero-config" style="width: 100%">
                <thead>
                    <tr>
                        <th style="text-align: center;">번호</th>
                        <th>제목</th>
                        <th>작성자</th>
                        <th>작성일</th>
                        <th style="text-align: center;">조회수</th>
                        <th style="text-align: center;">추천</th>
                    </tr>
                </thead>
                <tbody>
                    <c:forEach var="b" items="${boardList}">
                        <tr>
                            <td style="text-align: center;">${b.boaNo}</td>
                            <td>
                                <div class="d-flex justify-content-left align-items-center">
                                    <div class="d-flex flex-column">
                                        <span class="text-truncate fw-bold">
                                            [${b.catName}] <a href="${pageContext.request.contextPath}/board/${b.boaNo}">${b.title}</a>
                                        </span>
                                    </div>
                                </div>
                            </td>
                            <td>${b.ename}</td>
                            <td>${b.createDate}</td>
                            <td style="text-align: center;">${b.viewCnt}</td>
                            <td style="text-align: center;">${b.countLike}</td>
                        </tr>
                    </c:forEach>
                </tbody>
            </table>
        </div>
    </div>
    <!-- END 탭1 - 전체 -->

    <!-- 탭2 - 인기글 -->
    <!-- 추천수 10개 이상 -->

    <!-- 탭3 ~ -->
    <c:forEach var="ct" items="${categoryList}">
        <c:if test="${ct.catNo != 1}">
            <!-- 공지(catNo=1) 제외 -->
            <div class="tab-pane fade show" id="${ct.catNo}-tab-pane" role="tabpanel" aria-labelledby="tab-${ct.catNo}" tabindex="0">

                <div class="widget-content widget-content-area br-8">
                    <table id="${ct.catNo}-board-list" class="table dt-table-hover zero-config" style="width: 100%">
                        <thead>
                            <tr>
                                <th style="text-align: center;">번호</th>
                                <th>제목</th>
                                <th>작성자</th>
                                <th>작성일</th>
                                <th style="text-align: center;">조회수</th>
                                <th style="text-align: center;">추천</th>
                            </tr>
                        </thead>
                        <tbody>
                            <!-- ajax -->
                        </tbody>
                    </table>
                </div>
            </div>
        </c:if>
    </c:forEach>
    <!-- END 탭 -->

    </div>

모든 table에 적용하기 위해 class="zero-config"를 추가하여 호출

<!-- zero-config 적용/삭제 하는 함수 -->
<script>
    function initDataTable() {
        $('.zero-config').DataTable({
            "dom": "<'dt--top-section'<'row'<'col-12 col-sm-6 d-flex justify-content-sm-start justify-content-center'l><'col-12 col-sm-6 d-flex justify-content-sm-end justify-content-center mt-sm-0 mt-3'f>>>" +
                   "<'table-responsive'tr>" +
                   "<'dt--bottom-section d-sm-flex justify-content-sm-between text-center'<'dt--pages-count  mb-sm-0 mb-3'i><'dt--pagination'p>>",
            "oLanguage": {
                "oPaginate": { "sPrevious": '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-arrow-left"><line x1="19" y1="12" x2="5" y2="12"></line><polyline points="12 19 5 12 12 5"></polyline></svg>', 
                                "sNext": '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-arrow-right"><line x1="5" y1="12" x2="19" y2="12"></line><polyline points="12 5 19 12 12 19"></polyline></svg>' },
                "sInfo": "Showing page _PAGE_ of _PAGES_",
                "sSearch": '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-search"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line></svg>',
                "sSearchPlaceholder": "Search...",
               "sLengthMenu": "Results :  _MENU_",
                },
            "stripeClasses": [],
            "lengthMenu": [7, 10, 20, 50],
            "pageLength": 10 
            });
    }

    function destroyDataTable() {
        $('.zero-config').DataTable().destroy(); 
    }
</script>

적용, 삭제를 용이하게 하기위해 함수 생성

 

<script>
    $(document).ready(function() {
        // 기본적으로 전체 탭의 데이터를 로드
        tabData('전체');
        initDataTable();

        // 탭 클릭 이벤트
        $('#pills-tab button[data-bs-toggle="tab"]').click(function() {
            let buttonId = $(this).attr('id'); // 현재 클릭된 버튼의 ID
            let tabDataType;

            // tabDataType을 설정
            if (buttonId === 'tab-전체') {
                tabDataType = '전체';
            } else {
                tabDataType = buttonId.replace('tab-', ''); // tabDataType을 버튼 ID에서 'tab-'을 제거한 값 = catNo
            }

            tabData(tabDataType); // 해당 탭의 데이터를 로드
        });

        function tabData(tabData) {
            let url; 
            if (tabData === '전체') {
                url = '/board';
            } else {
                let catNo = tabData.replace('tab', '').trim();
                console.log(catNo);
                url = `/board/byCategory/`+catNo; // 카테고리별 게시글을 가져오는 URL
                console.log(url);
            }

            $.ajax({
                method: 'GET',
                url: url,
                success: function (data) {
                    console.log(data);
                    destroyDataTable(); // 이전 DataTable 인스턴스 삭제
                    let tableId = tabData === '전체' ? 'board-list' : tabData + '-board-list'; // 테이블 ID 선택 = catNo-board-list
                    console.log(tableId);

                    let table = $('#' + tableId).DataTable({ // 새로운 DataTable 인스턴스 생성
                        paging: true,
                        destroy: true, // 기존 데이터를 파괴하고 새로 초기화
                        "dom": "<'dt--top-section'<'row'<'col-12 col-sm-6 d-flex justify-content-sm-start justify-content-center'l><'col-12 col-sm-6 d-flex justify-content-sm-end justify-content-center mt-sm-0 mt-3'f>>>" +
                               "<'table-responsive'tr>" +
                               "<'dt--bottom-section d-sm-flex justify-content-sm-between text-center'<'dt--pages-count  mb-sm-0 mb-3'i><'dt--pagination'p>>",
                        "oLanguage": {
                            "oPaginate": { "sPrevious": '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-arrow-left"><line x1="19" y1="12" x2="5" y2="12"></line><polyline points="12 19 5 12 12 5"></polyline></svg>', 
                                            "sNext": '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-arrow-right"><line x1="5" y1="12" x2="19" y2="12"></line><polyline points="12 5 19 12 12 19"></polyline></svg>' },
                            "sInfo": "Showing page _PAGE_ of _PAGES_",
                            "sSearch": '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-search"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line></svg>',
                            "sSearchPlaceholder": "Search...",
                           "sLengthMenu": "Results :  _MENU_",
                            },
                        "stripeClasses": [],
                        "lengthMenu": [7, 10, 20, 50],
                        "pageLength": 10 
                    });

                    // 데이터 추가
                    data.forEach(item => {
                        // console.log(item);
                        let rowDate = [
                            item.boaNo,
                            `[\${item.catName}] <a href="/board/\${item.boaNo}">\${item.title}</a>`,
                            item.ename,
                            new Date(item.createDate).toLocaleString(), // 날짜 형식 변환
                            item.viewCnt,
                            item.countLike
                        ];
                        table.row.add(rowDate);
                    });
                    // console.log(data.length);
                    table.draw(); // 테이블 업데이트
                },
                error: function (xhr, status, error) {
                    console.error(`Error: ${status}, ${error}`);
                }
            });
        }
    });
</script>

ajax 호출 성공 시 인스턴스를 삭제하고 추가하도록 구현

 

해결..?

아직 약간 부족..

 

'구디아카데미 > Error' 카테고리의 다른 글

[Error] 모달 fetch 404  (0) 2025.01.23
[Error] Jsp <script> ${} 오류  (1) 2025.01.14
[Error] 400 오류 - Spring Security  (0) 2025.01.13
[Error] 500 오류  (0) 2024.11.14
[Error] 400 오류 / 검색 기능  (0) 2024.11.13