반응형
250x250
Notice
Recent Posts
Recent Comments
Link
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
Archives
Today
Total
관리 메뉴

샘오리_개발노트

날짜/달력 API를 사용해서 기간으로 조회/검색하기 (쉬움) 본문

개발자 전향 프로젝트

날짜/달력 API를 사용해서 기간으로 조회/검색하기 (쉬움)

샘오리 2023. 1. 10. 12:55
728x90
반응형

https://www.daterangepicker.com/

 

Date Range Picker — JavaScript Date & Time Picker Library

Originally created for reports at Improvely, the Date Range Picker can be attached to any webpage element to pop up two calendars for selecting dates, times, or predefined ranges like "Last 30 Days". To get started, include jQuery, Moment.js and Date Range

www.daterangepicker.com

 

기술스택

  • 자바 17
  • 스프링부트
  • JPA + QueryDSL

프로세스

  • HTML에 Date Range Picker 라는 CDN API를 Import 해준다.
  • HTML에 기간을 입력/설정할 수 있는 input 태그를 하나 만들어준다.
  • 호출해온 위 API를 사용해서 JavaScript에서 날짜/달력에 관한 설정을 해준다.
  • 해당 설정을 html의 input 태그에 적용하여 사용자가 input 태그를 클릭 했을 때 달력이 팝업되도록 한다.
  • 팝업된 달력에서 사용자가 날짜/시간 값을 설정한 뒤 apply 버튼을 클릭 하면 trigger 되는 코드를 작성한다.
  • 여기서 시작날짜/시간과 종료날짜/시간을 구분하여 두개의 인자로 컨트롤러에 쏴주고 백엔드 소스를 거친다.
  • DB 조회를 할 때 입력받아온 값과 DB의 값과 대조한다.
  • *시작날짜/시간보다는 같거나 크며, 종료날짜/시간보다는 작거나 같은 값을 조회한다.
  • 선택적으로 뽑아온 데이터를 뿌려줌으로써 기간 조회가 완성되는 프로세스 이다.

1. HTML에 Date Range Picker 라는 CDN API를 Import 해준다.

<script type="text/javascript" src="https://cdn.jsdelivr.net/jquery/latest/jquery.min.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/momentjs/latest/moment.min.js"></script>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/daterangepicker/daterangepicker.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/daterangepicker/daterangepicker.css" />

2. HTML에 기간을 입력/설정할 수 있는 input 태그를 하나 만들어준다.

<input type="text" name="datetimes" />

3. 호출해온 위 API를 사용해서 JavaScript에서 날짜/달력에 관한 설정을 해준다.

//외부 Javascript 파일을 사용할 경우

$(function() {
  $('input[name="datetimes"]').daterangepicker({
    timePicker: true,
    startDate: moment().startOf('hour'),
    endDate: moment().startOf('hour').add(32, 'hour'),
    locale: {
      format: 'M/DD hh:mm A'
    }
  });
});


//HTML내 Inline Script tag를 사용할 경우

<script>
$(function() {
  $('input[name="datetimes"]').daterangepicker({
    timePicker: true,
    startDate: moment().startOf('hour'),
    endDate: moment().startOf('hour').add(32, 'hour'),
    locale: {
      format: 'M/DD hh:mm A'
    }
  });
});
</script>

4. 해당 설정을 html의 input 태그에 적용하여 사용자가 input 태그를 클릭 했을 때 달력이 팝업되도록 한다.

제이쿼리 selector가 올바른 input 태그를 select 했는지 확인하면 되는데
이 예시의 경우 input 태그의 ID나 CLASS를 설정하지 않고 name으로만 설정했기 때문에
위 소스코드처럼 $('input[name="datetimes"]') 이런식으로 선택해주면 된다.
*ID를 설정해주는 것도 방법이다.

5. 팝업된 달력에서 사용자가 날짜/시간 값을 설정한 뒤 apply 버튼을 클릭 하면 trigger 되는/발동되는 코드를 작성한다.

 

아래는 API 공식 문서에서 어떻게 시작날짜/시간과 종료날짜/시간을 사용할 수 있는지 나와있는 예시이다.

$('#daterange').on('apply.daterangepicker', function(ev, picker) {
  console.log(picker.startDate.format('YYYY-MM-DD'));
  console.log(picker.endDate.format('YYYY-MM-DD'));
});

이 예시 코드를 사용해서 우리는 apply 버튼을 클릭했을 때 trigger되는/ 발동되는 코드안에서 시작/종료 날짜를 받아오는 방법을 알 수 있다.

제이쿼리 selector는 input 태그의 이름으로 받아왔기 때문에 selector를 일단 $('input[name="datetimes"]')로 바꾸고

저 시작/종료 날짜를 console.log에 찍는 것이 아니라 택배에 보낼 물건 포장해서 보내듯 변수에 담아 컨트롤러에 인자로 담아서 보내야 할 것이다.

 

심플하게 아래처럼 바꾸면 가능하다. 

$('input[name="datetimes"]').on('apply.daterangepicker', function(ev, picker) {
  let startDate = picker.startDate.format('YYYY-MM-DD');
  let endDate = picker.endDate.format('YYYY-MM-DD');
});

6. 여기서 시작날짜/시간과 종료날짜/시간을 구분하여 두개의 인자로 컨트롤러에 쏴주고 백엔드 소스를 거친다.

위에서 이미 여기서 시작날짜/시간과 종료날짜/시간을 구분하여 두개의 변수에 각각 담아두었기에 이제 보낼일만 남았다.

$('input[name="datetimes"]').on('apply.daterangepicker', function (ev, picker) {

  let startDate = picker.startDate.format('YYYY-MM-DD');
  let endDate = picker.endDate.format('YYYY-MM-DD');
  
    $.ajax({
        type: 'GET',
        url: '/경로',
        data: {startDate: startDate, endDate: endDate},
        success: function (data) {
            if (data) {
                //성공 시 하고싶은 작업
            }
        }
    })
})

ajax를 이용하여 컨트롤러에 data를 담아 보내주는 작업은 위와 같은 샘플코드로 가능하며, 데이터 전송이 성공했을 때

발동하고 싶은 동작을 if(data){ 이곳에 적어주면 된다 }

* 필자 같은 경우 비동기로 화면 깜빡임 없이 기간 조회하여 선택된 데이터를 VIEW 테이블안에 알맹이만 갱신해주고 싶기 때문에 아래와 같은 코드를 사용했다.

 

  if (data) {
                $('#테이블을 감싸는 DIV ID').replaceWith(data);
            }

컨트롤러

  @GetMapping("/경로")
    public String 함수명(Model model, Pageable pageable, @RequestParam(value = "startDate", required = false) String startDate, @RequestParam(value = "endDate", required = false) String endDate) {
        Page<DTO 명> p;
        
        p = 서비스 참조변수 명.서비스 내의 함수명(pageable, startDate,endDate);
        
        model.addAttribute("뽑아온 데이터를 담을 변수", p);
        
        // 페이징 관련하여 다른 함수에도 사용되어 전역 추출한 함수로 오늘의 주제와 상관 없기에 패스
        // 페이징은 블로그의 페이징관련 글을 보고 구현해보기!
        paging(model, p);
        
        return "HTML 이름 :: #테이블을 감싸고 있는 DIV ID";

서비스

public Page<DTO 명> 함수명(Pageable pageable, String startDate, String endDate) {
    return QueryDSL 인터페이스 참조변수명.함수명(startDate,endDate, pageable);
}

 

QueryDSL 인터페이스

 

Page<DTO 명> 함수명(String startDate, String endDate, Pageable pageable);

 

7. DB 조회를 할 때 입력받아온 값과 DB의 값과 대조한다. 

*시작날짜/시간보다는 같거나 크며, 종료날짜/시간보다는 작거나 같은 값을 조회한다.

 

QueryDSL 구현체

@Override
public Page<DTO 명> 함수명(String startDate, String endDate, Pageable pageable) {
// 아래는 조건에 부합하는 데이터를 뽑아와서 List에 담아주기 위해 필요한 코드
    List<DTO 명> content = jpaQueryFactory    // (1) 조회한 결과 리스트에 담기
            .selectFrom(static으로 import 해와야 하는 QueryDSL 전용 DTO의 참조변수 a.k.a QueryDSL참조변수)
            .where(
                    QueryDSL참조변수.날짜가 있는 칼럼.goe(startDate).and(QueryDSL참조변수.날짜가 있는 칼럼.loe(endDate)))
            .offset(pageable.getOffset())   // (2) 페이지 번호
            .limit(pageable.getPageSize())  // (3) 페이지 사이즈
            .fetch();
// 아래는 뽑아온 데이터를 페이징할 때 필요한 코드
    JPAQuery<Long> count = jpaQueryFactory        // (4) 검색 결과 값의 개수
            .select(QueryDSL참조변수.count())
            .from(QueryDSL참조변수)
            .where(
                    QueryDSL참조변수.날짜가 있는 칼럼.goe(startDate).and(QueryDSL참조변수.날짜가 있는 칼럼.loe(endDate)));

    return PageableExecutionUtils.getPage(content, pageable, count::fetchOne);    // (6) PageImpl 반환
}

* 여기서 눈여겨볼점은 goe와 loe인데 예측했을 수도 있지만 greater or equal to, less or equal to라는 뜻으로

크거나 같다와 작거나 같다를 QueryDSL 라이브러리에서 쉽게 사용할 수 있도록 함수화 해놓은 것이다.

 

기본 문법에 관심이 많다면 이전 글을 참조하면 된다.

https://samori.tistory.com/59

 

[JAVA] JPA 활용법 -3 (QueryDSL 활용해보기) + 기본 문법

https://samori.tistory.com/58 [JAVA] JPA 활용법 -2 (QueryDSL 활용해보기) https://samori.tistory.com/52 [JAVA] JPA 활용법 -1 (QueryDSL 적용해보기) QueryDSL이란? Spring Boot Data JPA 는 쿼리문을 직접 짜지 않아도 함수명만 알

samori.tistory.com

8. 다시 컨트롤러로 돌아와서 선택적으로 뽑아온 데이터를 HTML에 특정 DIV에만 뿌려줌으로써

비동기적인 기간 조회가 완성되는 프로세스 이다.

  @GetMapping("/경로")
    public String 함수명(Model model, Pageable pageable, @RequestParam(value = "startDate", required = false) String startDate, @RequestParam(value = "endDate", required = false) String endDate) {
        Page<DTO 명> p;
        
        p = 서비스 참조변수 명.서비스 내의 함수명(pageable, startDate,endDate);
        
        model.addAttribute("뽑아온 데이터를 담을 변수", p);
        
        // 페이징 관련하여 다른 함수에도 사용되어 전역 추출한 함수로 오늘의 주제와 상관 없기에 패스
        // 페이징은 블로그의 페이징관련 글을 보고 구현해보기!
        paging(model, p);
        
        return "HTML 이름 :: #테이블을 감싸고 있는 DIV ID";

추가 커스터마이징을 거친 달력

728x90
반응형
Comments