4월 8일

SJY0000·2022년 4월 8일
0

Springboot

목록 보기
11/24

오늘 배운 것

  • pagination
  • 에디터 적용하기
  • 기본페이지 만들기(1)

pagination

  • index 페이지에 pagination 적용
  • @RequestParam으로 현재 페이지값을 넘겨주고, pageable 객체로 pagination 적용
  • 적용할 데이터를 page타입으로 선언, 페이지 수를 계산하여 index페이지로 전송
	@GetMapping
	public String index(Model model, @RequestParam(value = "page", defaultValue = "0") Integer page) {
		int perPage = 6; // @RequestParam에 같이 적어도 되지만 이번엔 따로 적기 (한 페이지당 최대 6개)
		Pageable pageable = PageRequest.of(page, perPage); // 표시할 페이지, 한 페이지에 표시할 데이터 수(6개)
		// data.domain.page
		Page<Product> products = productRepo.findAll(pageable);
		List<Category> categories = categoryRepo.findAll();

		// Category id와 name을 map에 담아 index페이지에 전송
		HashMap<Integer, String> cateIdAndName = new HashMap<>();
		
		for (Category category : categories) {
			cateIdAndName.put(category.getId(), category.getName());
		}

		model.addAttribute("products", products);
		model.addAttribute("cateIdAndName", cateIdAndName);
		
		// Pagenation을 위해 필요한 정보
		long count = productRepo.count(); // 전체 갯수 (long 타입으로 Return)
		double pageCount = Math.ceil((double)count / (double)perPage); // 13/ 6 = 2.12, int로 나누면 소수점이 출력이 안되기때문에 double타입으로 계산한다.
		
		model.addAttribute("pageCount",pageCount); // 총페이지
		model.addAttribute("perPage", perPage);		// 페이지당 표시 아이템수
		model.addAttribute("count", count);			// 총 아이템 갯수
		model.addAttribute("page", page);			// 현재 페이지
		
		return "/admin/products/index";
	}
  • table 밑에다가 태그 삽입
  • page는 0부터 시작하므로 총 페이지 수에서 -1을 해줘야 해당하는 페이지로 이동
  • 선택한 페이지번호에 active class를 추가하여 표시를 함
        <!-- 부트스트랩 페이지네이션 -->
        <nav class="mt-3" th:if="${count > perPage}">
          <ul class="pagination">
            <li class="page-item" th:if="${page > 0}">
              <a th:href="@{/admin/products/} + '?page=__${page-1}__'" class="page-link">이전</a>
            </li>
            <!-- sequence(a,b) a와 b 사이의 숫자들을 가지고 있음-->
            <li class="page-item" th:each="number : ${#numbers.sequence(0, pageCount-1)}" th:classappend="${page==number} ? 'active' : ''">
              <a th:href="@{/admin/products/} + '?page=__${number}__'" class="page-link" th:text="${number+1}"></a>
            </li>
            <li class="page-item" th:if="${page < pageCount-1}">
              <a th:href="@{/admin/products/} + '?page=__${page+1}__'" class="page-link">다음</a>
            </li>
          </ul>
        </nav>

참고(pageable)

https://wonit.tistory.com/483


에디터적용하기

CK에디터 CDN

https://ckeditor.com/docs/ckeditor5/latest/builds/guides/quick-start.html

  • footer에 cdn추가(jquery, bootstrap 밑에다가 추가)
  • js에 추가
  • textarea 태그의 id값이 존재하면 에디터 적용
  // page conenet ck에디터 추가
  if ($('#content').length) {
    // JQuery에서는 태그선택시 무조건 true이기 때문에 length(없으면 0, 있으면 1)를 사용
    ClassicEditor.create(document.querySelector('#content')).catch((error) => {
      console.error(error);
    });
  }
  // product description ck에디터 추가
  if ($('#description').length) {
    // JQuery에서는 태그선택시 무조건 true이기 때문에 length(없으면 0, 있으면 1)를 사용
    ClassicEditor.create(document.querySelector('#description')).catch((error) => {
      console.error(error);
    });
  }


기본페이지 만들기(1)

설정

  • Main Package에 모든 Controller에 적용할 클래스 생성
  • 모든 페이지에 존재하는 nav태그와 category들을 어느 페이지에 가더라도 출력될 수 있도록 함
package com.myapp.shoppingmall;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ModelAttribute;

import com.myapp.shoppingmall.dao.CategoryRepository;
import com.myapp.shoppingmall.dao.PageRepository;
import com.myapp.shoppingmall.entities.Category;
import com.myapp.shoppingmall.entities.Page;

// 모든 Controller에 적용
@ControllerAdvice
public class Common {

	@Autowired
	private PageRepository pageRepo;
	
	@Autowired
	private CategoryRepository categoryRepo;
	
	@ModelAttribute
	public void sharedData(Model model) {
		// cpages에 모든 페이지들을 순서대로 담아서 전달
		List<Page> cpages = pageRepo.findAllByOrderBySortingAsc();
		List<Category> categories = categoryRepo.findAll();
		
		model.addAttribute("cpages", cpages);
		model.addAttribute("ccategories", categories);
	}
}

pageController

  • 기본 메인페이지 설정
  • nav태그의 입력된 Page를 클릭 시 해당 페이지로 이동
package com.myapp.shoppingmall.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
/**
 * 
 * 쇼핑몰 기본 홈페이지
 *
 */

import com.myapp.shoppingmall.dao.PageRepository;
import com.myapp.shoppingmall.entities.Page;

@Controller
@RequestMapping("/")
public class PageController {

	@Autowired
	private PageRepository pageRepo;
	
	@GetMapping
	public String home(Model model) {
		// entities의 page
		Page page = pageRepo.findBySlug("home");
		
		model.addAttribute("page", page);
		
		return "page"; // page.html로 이동
	}
	@GetMapping("/{slug}")
	public String page(@PathVariable("slug") String slug, Model model) {
		Page page = pageRepo.findBySlug(slug);
		
		if (page == null) {
			return "redirect:/"; // 페이지가 없으면 home으로 이동
		}
		model.addAttribute("page", page);
		
		return "page";
	}
}
  • DB Page 테이블에 입력된 content값을 불러와서 출력
  • category List를 출력
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
  <head th:replace="/fragments/head :: head-front"></head>
  <body>
    <nav th:replace="/fragments/nav :: nav-front"></nav>
    <main role="main" class="container-fluid mt-5">
      <div class="row">
        <div th:replace="/fragments/categories :: categories"></div>
        <div class="col"></div>
        <div class="col-7" th:utext="${page.content}"></div>
        <div class="col"></div>
      </div>
    </main>
    <footer th:replace="/fragments/footer :: footer"></footer>
  </body>
</html>

상단 nav바에서 다른 페이지 클릭했을 시 이동

Category 클릭 시 상품출력

  • Category 클릭 시 선택한 category의 slug값으로 상품 검색하여 저장
  • 모든 상품을 보여주는 all 과 Category별 상품을 보여주기
  • pageable 객체로 Pagenation 사용
package com.myapp.shoppingmall.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import com.myapp.shoppingmall.dao.CategoryRepository;
import com.myapp.shoppingmall.dao.ProductRepository;
import com.myapp.shoppingmall.entities.Category;
import com.myapp.shoppingmall.entities.Product;

@Controller
@RequestMapping("/category")
public class CategoryController {

	@Autowired
	private CategoryRepository categoryRepo;
	
	@Autowired
	private ProductRepository productRepo;
	
	/**
	 * 입력된 slug 카테고리별로 제품리스트 표시(페이징 포함)
	 * @param slug 카테고리 slug
	 * @param page 표시할 페이지 번호
	 * @return products 페이지로 이동
	 */
	
	@GetMapping("/{slug}")
	public String category(@PathVariable("slug") String slug, Model model, @RequestParam(value = "page", defaultValue = "0") Integer page) {
		int perPage = 6; // @RequestParam에 같이 적어도 되지만 이번엔 따로 적기 (한 페이지당 최대 6개)
		Pageable pageable = PageRequest.of(page, perPage); // 표시할 페이지, 한 페이지에 표시할 데이터 수(6개)
		long count = 0;
		
		// Category 선택(all , 그외 개별 가테고리)
		if(slug.equals("all")) {
			Page<Product> products = productRepo.findAll(pageable);
			count = productRepo.count(); // 전체 상품 수
			
			model.addAttribute("products", products); // 모든 카테고리 상품들
		} else { // Category 개별 선택
			Category category = categoryRepo.findBySlug(slug);
			if(category == null) {
				return "redirect:/"; // Category가 없으면 home으로 이동
			}
			String categoryId = Integer.toString(category.getId());
			String categoryName = category.getName();
			List<Product> products = productRepo.findAllByCategoryId(categoryId, pageable);
			count =productRepo.countByCategoryId(categoryId);
			
			model.addAttribute("products", products); // 선택한 Category의 상품들
			model.addAttribute("categoryName", categoryName);
		}

		// Pagenation을 위해 필요한 정보
		double pageCount = Math.ceil((double)count / (double)perPage); // 13/ 6 = 2.12, int로 나누면 소수점이 출력이 안되기때문에 double타입으로 계산한다.
		
		model.addAttribute("pageCount",pageCount); // 총페이지
		model.addAttribute("perPage", perPage);		// 페이지당 표시 아이템수
		model.addAttribute("count", count);			// 총 아이템 갯수
		model.addAttribute("page", page);			// 현재 페이지
		
		return "products"; // products.html 페이지로 이동
	}
}
  • 삼항연산자를 이용해 CategoryName 출력
  • @{${#httpServletRequest.requestURI}}는 현재 보고있는 페이지 주소를 출력
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
  <head th:replace="/fragments/head :: head-front"></head>
  <body>
    <nav th:replace="/fragments/nav :: nav-front"></nav>
    <main role="main" class="container-fluid mt-5">
      <div class="row">
        <div th:replace="/fragments/categories :: categories"></div>
        <div class="col"></div>
        <div class="col-8">
          <!-- CategoryName이 있으면 출력하고 없으면 모든제품 출력-->
          <h2 class="display-3 mb-5" th:text="${categoryName} ?: '모든상품'"></h2>
          <div class="row">
            <div class="col-4" th:each="product : ${products}">
              <p>
                <img th:src="@{'/media/' + ${product.image}}" style="width: 200px" />
              </p>
              <h4 th:text="${product.name}"></h4>
              <div class="desc" th:utext="${product.description}"></div>
              <p th:text="${product.price}+ '원'"></p>
            </div>
          </div>
          <!-- 부트스트랩 페이지네이션 -->
          <nav class="mt-3" th:if="${count > perPage}">
            <ul class="pagination">
              <!-- @{${#httpServletRequest.requestURI}} 현재 페이지 주소, 지금은 @{/category/category.slug} -->
              <li class="page-item" th:if="${page > 0}">
                <a th:href="@{${#httpServletRequest.requestURI}} + '?page=__${page-1}__'" class="page-link">이전</a>
              </li>
              <!-- sequence(a,b) a와 b 사이의 숫자들을 가지고 있음-->
              <li class="page-item" th:each="number : ${#numbers.sequence(0, pageCount-1)}" th:classappend="${page==number} ? 'active' : ''">
                <a th:href="@{${#httpServletRequest.requestURI}} + '?page=__${number}__'" class="page-link" th:text="${number+1}"></a>
              </li>
              <li class="page-item" th:if="${page < pageCount-1}">
                <a th:href="@{${#httpServletRequest.requestURI}} + '?page=__${page+1}__'" class="page-link">다음</a>
              </li>
            </ul>
          </nav>
        </div>
      </div>
    </main>
    <footer th:replace="/fragments/footer :: footer"></footer>
  </body>
</html>

모든 Category 상품 출력

개별 Category 상품 출력

참고(Thymeleaf 기본 문법)

https://chung-develop.tistory.com/5

0개의 댓글