본문 바로가기
개발/Spring

[SpringBoot] Autocomplete을 이용한 자동완성기능 구현하기

by 코딩하는 흰둥이 2024. 7. 22.

Autocomplete 는 jQuery 의 함수 중 하나로

사용자가 입력한 데이터를 실시간 감지하여 연관되는 데이터를 자동완성시켜 주는 기능을 한다

 

 

jQuery
  <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
  <link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
  <script src="https://code.jquery.com/jquery-3.7.1.js}" integrity="sha256-eKhayi8LEQwp4NKxN+CfCh+3qOVUtJn3QNZ0TciWLP4=" crossorigin="anonymous"></script>

 

 

html
<div class="form-group row">
    <div class="col-sm-5 mb-3 mb-sm-0">
        <select class="form-control form-control-user" id="selectApproval1"
                name="selectApproval" onchange="autoUserInfo(this)">
            <option value="">전체</option>
            <option value="경영">경영</option>
            <option value="영업">영업</option>
            <option value="개발">개발</option>
        </select>
    </div>
</div>

<div class="form-group row">
    <div class="col-sm-5 mb-3 mb-sm-0">
        <input type="text" id="autocomplete" class="form-control form-control-user autocomplete-input" placeholder="결재자를 입력해주세요">
    </div>
</div>
<div class="form-group" id="selectUser"></div>

 

 

js
// 결재자 변수
let tData;

// 결재자 부서 선택 변수
let selectDepartValue = "";

// label 과 value로 설정할때 사용
const tData2 = [{label : "대표", value : "1"},{label : "부장", value : "2"},{label : "과장", value : "3"},{label : "대리", value : "4"}];

// 결재자 정보 가져오기
function autoUserInfo(e) {
    // e 가 '' 면 바인딩한 데이터가 없다
    if(e != ''){
        selectDepartValue = e.value;
    }

    $.ajax({
        url : "/autoUserInfo",
        type : "GET",
        data : {"depart" : selectDepartValue},
        async : false,                  // 데이터를 먼저 가져와서 변수에 세팅해줘야 autocomplete 에서 해당 데이터를 인지한다
        success : function (data){
            if(data != ""){
            // 가져온 유저 정보를 담는다
                tData = data;
            }
        },error(e) {
            alert("에러가 발생하였습니다");
        }
    });
}

// 결재자 삭제
$(document).on('click','.btn-icon-split',function (){
    // 배열에 결재자 재정의
    tData.push($(this)[0].innerText)
    // 선택한 결재자 삭제
    $(this).remove();
    count--;
});


// 결재자 인원수 
let count = 0;
$(document).ready(function (){
    // 결재자 정보가져오기
    autoUserInfo(selectDepartValue);

    // autocomplete - 자동완성기능 설정하기
    $("#autocomplete").autocomplete({
        // 사용자가 입력한 데이터와 비교
        source: tData,
        // 사용자가 입력한 데이터가 한글자일때부터
        minLength : 1,
        // 방향키로 내리다보면 선택하지 않았는데 선택이 된다 false 로 지정
        focus: function (event, ui){
            return false;
        },
        //데이터 선택했을때 실행
        select : function(event, ui) {
            if(count >= 4){
                alert("4명까지 선택 가능합니다.");
                return;
            }

            count++;
            // 선택한 결재자를 출력해주기 위함
            $("#selectUser").append('<a href="#" class="btn btn-light btn-icon-split"><span class="icon text-gray-600"><i class="fas fa-times"></i></span><span class="text" id="uiValue'+ count +'">' + ui.item.value +'</span></a>')

			// label과 value로 사용할 경우 사용, 다른 코드들도 맞춰서 수정해야한다
			//$("#selectUser").append('<a href="#" class="btn btn-light btn-icon-split"><span class="icon text-gray-600"><i class="fas fa-times"></i></span><span class="text" id="uiValue'+ count +'">' + ui.item.label +'</span></a>')


            // 선택한 결재자 배열에서 삭제
            tData = tData.filter((e) => e !== ui.item.value);

            // 재정의한 배열을 다시 바인딩
            $("#autocomplete").autocomplete({source: tData});
        }
    });

});

 

 

 

 

controller
import com.example.practice.service.approval.ApprovalService;
import com.example.practice.vo.UserVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;

@RestController
public class ApprovalController {

    @Autowired
    private ApprovalService approvalService;

    @RequestMapping("/autoUserInfo")
    public List<String> autoUserInfo(@RequestParam  String depart) throws Exception {
    	// db에서 depart의 부서값에 해당하는 유저 정보를 가져온다 
        List<UserVo> vo = approvalService.autoUserInfo(depart);
        List<String> result = new ArrayList<>();

	// 이름만 담아서 retrun
        for (int i = 0; i < vo.size(); i++) {
            result.add(vo.get(i).getName());
        }
        return result;
    }

}

 

 

 

 

mapper
    <select id="autoUserInfo" resultType="com.example.practice.vo.UserVo">
        SELECT
            NAME,
            DEPARTMENT,
            POSITION
        FROM USERMEMBER
        WHERE ENABLED = 'Y'
        AND NAME != '운영자'
        <if test ="depart != null and !('').equals(depart)" >
            AND DEPARTMENT = #{depart}
        </if>
    </select>

 

 

 

 

TEST

기본 폼

 

 

 

김대리를 선택하고 다시 김을 입력해보면 김대리가 없어진 것이 확인된다

 

4명 이상 선택 시 알림

 

 

김부장을 삭제하면 다시 자동완성에 출력되는것을 확인

 

 

 

 

기본 코드정도만 올려놓았으며, 

Bootstrap을 사용하고 있지만 결재자를 선택했을때

x 표나오는 부분을 제외하고는 Bootstarp이 필요가 없다 참고.

 

Autocomplete 설정기능은 더 있으니 필요한것은 찾아서 적용하길 바란다

 


 

추가
// 자동완성 할 데이터 정보
let searrchData = [];

/**
 * 정보 가져오기
 */
function searchMenu(){
    $.ajax({
        url : "/searchMenu",
        type : "GET",
        async: false,
        success : function (data) {
            if(data != null){
            // label , value 형태로 만들기
            // name: item.name 같은 name 도 지정 가능
                for (let i = 0; i < data.length; i++) {
                    searrchData = data.map(item => ({
                        label: item.name,
                        value: item.path
                    }))
                }
            }
        },
        error(e){
            console.log("error : "+ e);
        }
    });
}

 

 

 

    // autocomplete - 자동완성기능 설정하기
    $("#autocomplete").autocomplete({
        // 사용자가 입력한 데이터와 비교
        source: searrchData,
        // 사용자가 입력한 데이터가 한글자일때부터
        minLength : 1,
        // 방향키로 내리다보면 선택하지 않았는데 선택이 된다 false 로 지정
        focus: function (event, ui){
            return false;
        },
        //데이터 선택했을때 실행
        select : function(event, ui) {
        
               // 선택시 value 값이 찍히는 것을 방지
               event.preventDefault();
               
               // 선택한 메뉴 데이터 표시
               $("#autocomplete").val(ui.item.label);

            }
        }
    });

 

event.preventDefault();

자동완성 된 데이터를 클릭하면 value 값이 항상 찍히는데 그걸 막아준다

댓글