Dandy Now!
  • [개발자의품격][부트캠프][1기][14차시] JavaScript 주요 포인트 #21 | 데이터 그리드 - 정렬, 필터, 페이징
    2022년 02월 28일 19시 24분 19초에 업로드 된 글입니다.
    작성자: DandyNow
    728x90
    반응형

    JavaScript 주요 포인트 #21

    데이터 그리드

    정렬

    컬럼 클릭 시 정렬 기능 구현

    <!-- 테이블의 컬럼 클릭 시 오름차순/내림차순 정렬 기능 구현 -->
    <tr>
      <th><input type="checkbox" id="chks" onchange="checkAll()" /></th>
      <!-- data-sort-key는 커스텀 속성으로서 얼마든지 만들 수 있다. -->
      <th data-sort-key="name">Name</th>
      <th data-sort-key="company">Company</th>
      <th data-sort-key="gender">Gender</th>
      <th>Age</th>
      <th data-sort-key="email">Email</th>
      <th data-sort-key="phone">Phone</th>
      <th data-sort-key="address">Addres</th>
    </tr>
    <script>
      // HTML이 모두 정상적으로 load되는 순간
      window.addEventListener("load", () => {
        // querySelectorAll로 "th[data-sort-key]"들을 찾아내고
        // 여러 건이므로 forEach 함수로 for 문을 돌리면서 각각의 th를 가져오고
        document.querySelectorAll("th[data-sort-key]").forEach((th) => {
          // addEventListener로 클릭 이벤트가 일어 났을때 sort함수를 호출한다.
          th.addEventListener("click", () => {
            // 파라미터로는 data-sort-key에 있는 값으로 정렬 하겠다.
            sort(th.getAttribute("data-sort-key"));
          });
        });
      });
    </script>
    <script>
      // 정렬에 사용하기 위한 sort 함수
      let lastSortKey = "";
      let bAsc = true;
    
      function sort(sortKey) {
        // 동일 컬럼 연속해서 누룰 때 오름차순/내림차순 처리
        if (sortKey === lastSortKey) {
          bAsc = !bAsc;
        }
    
        let sortValue = bAsc ? 1 : -1;
    
        const sortData = customerData.sort(function (a, b) {
          //   숫자 값이 포함되어 있을 경우 처리
          //   if (sortKey === "age") {
          //     return bAsc ? a - b : b - a;
          //   } else {
          if (a[sortKey].toLowerCase() > b[sortKey].toLowerCase()) { // toLowerCase 사용하여 대소문자 구분없이 정렬
            return sortValue;
          } else if (a[sortKey].toLowerCase() < b[sortKey].toLowerCase()) {
            return sortValue * -1;
          } else {
            return 0;
          }
          //   }
        });
    
        renderTable(sortData); // 정렬된 데이터를 화면에 그려준다.
        lastSortKey = sortKey;
      }
    </script>

     


     

    필터

    <tr>
      <th></th>
      <th><input type="search" name="" id="" data-filter-key="name" /></th>
      <th>
        <input type="search" name="" id="" data-filter-key="company" />
      </th>
      <th></th>
      <th></th>
      <th><input type="search" name="" id="" data-filter-key="email" /></th>
      <th></th>
      <th></th>
    </tr>
    <script>
      window.addEventListener("load", () => {
        document.querySelectorAll("input[data-filter-key]").forEach((input) => {
          input.addEventListener("keyup", () => {
            filter(input.getAttribute("data-filter-key"));
          });
        });
      });
    </script>
    <script>
      function filter(filterKey) {
        // 13번은 엔터 입력을 말한다.
        if (event.keyCode === 13) {
          // filterValue는 input type="search"의 값
          const filterValue = event.target.value;
          // filterData의 기본값은 customerData 전체값
          let filterData = customerData;
          // filterValue 값이 있으면 filterData는 filter 함수에 의해 customerData 전체값 중 filterValue와 일치하는 데이터만 필터리링
          if (filterValue !== "") {
            filterData = customerData.filter(
              (c) => c[filterKey].toLowerCase().indexOf(filterValue) > -1
            );
          }
          renderTable(filterData);
        }
      }
    </script>

     

    [그림 1] 필터 기능 적용

     


     

    페이징

    <style>
      .pagination {
        display: inline-block;
        margin-top: 10px;
      }
    
      .pagination a {
        color: black;
        float: left;
        padding: 8px 16px;
        text-decoration: none;
        cursor: pointer;
      }
    
      .pagination a.active {
        background-color: deeppink;
        color: white;
      }
    </style>
    <div class="pagination"></div>
    <script>
      let customerData = [];
      async function doSearch() {
        const gender = document.querySelector("#gender").value;
        const name = document.querySelector("#name").value;
    
        let resource = "http://localhost:3000/customers";
        if (gender === "") {
          if (name !== "") {
            resource = `http://localhost:3000/customers?name_like=${name}`;
          }
        } else {
          if (name === "") {
            resource = `http://localhost:3000/customers?gender=${gender}`;
          } else {
            resource = `http://localhost:3000/customers?gender=${gender}&name_like=${name}`;
          }
        }
        
        const res = await fetch(resource);
        const resJson = await res.json();
        customerData = resJson;
        console.log(resJson);
        
        // 조회 버튼 누룰시 0~pagecnt 만큼 출력
        renderTable(resJson.slice(0, pagecnt)); // 페이지당 row 수
        paging();
      }
    </script>
    <script>
      let totalPage = 0;
      const pagecnt = 3; // 페이지 당 row 수
      let pageRange = [];
      let currentPage = 1; // 현재 페이지
      let showList = [];
    
      // 전체 페이지 수
      function paging() {
        totalPage = Math.ceil(customerData.length / pagecnt);
    
        if (totalPage > 5) {
          pageRange = [1, 2, 3, 4, 5];
        } else {
          pageRange = [];
          for (var i = 1; i <= totalPage; i++) {
            pageRange.push(i);
          }
        }
    
        renderPagination();
      }
    
      // 페이지 번호 렌더링
      function renderPagination() {
        const h = [];
        // 왼쪽으로 넘어가는 "«"가 보이는 경우
        if (pageRange[0] > 1) {
          h.push(`<a href="javascript:prePage();">&laquo;</a>`); // &laquo는 "«" 특수문자이다.
        }
    
        for (const no of pageRange) {
          h.push(
            `<a href="javascript:changePage(${no});" class="${
              no === currentPage ? "active" : "" // active로 인해 현재 페이지 숫자에 active(deeppink css) 적용됨
            }">${no}</a>`
          );
        }
    
        // 오른쪽으로 넘어가는 "»"가 보이는 경우
        if (pageRange[pageRange.length - 1] < totalPage) {
          h.push(`<a href="javascript:nextPage();">&raquo;</a>`); // &raquo는 "»" 특수문자이다.
        }
    
        document.querySelector(".pagination").innerHTML = h.join("");
      }
    
      // "»" 누를 시 처리
      function nextPage() {
        const pageNo = pageRange[pageRange.length - 1];
        const startIdx = pageNo + 1;
        let endIdx = pageNo + 5;
        if (endIdx > totalPage) {
          endIdx = totalPage;
        }
    
        pageRange = [];
        for (let i = startIdx; i <= endIdx; i++) {
          pageRange.push(i);
        }
    
        changePage(pageNo + 1);
      }
    
      // "«" 누를 시 처리
      function prePage() {
        const pageNo = pageRange[0]; //6
        pageRange = [pageNo - 5, pageNo - 4, pageNo - 3, pageNo - 2, pageNo - 1];
        changePage(pageNo - 1);
      }
    
      // 페이지 변경시 해당 데이터 렌더링
      function changePage(pageNo) {
        currentPage = pageNo;
        const startIdx = (pageNo - 1) * pagecnt;
        let endIdx = pageNo * pagecnt;
        if (endIdx > customerData.length) {
          endIdx = customerData.length;
        }
    
        renderTable(customerData.slice(startIdx, endIdx));
        // if (onlyRenderPaging) {
        renderPagination();
        // } else {
        //   paging();
        // }
      }
    </script>

     

    [그림 2] 페이징 처리

    728x90
    반응형
    댓글