Select2, AutoComplete을 지원하는 select 확장 플러그인

1% 부족한 select 엘러먼트

HTML5에서는 select 엘러먼트를 이용하여 ComboBox 컨트롤을 구현할 수 있다. 하지만 기본 엘러먼트만으로는 기대치가 높은 사용자의 까다로운 요구를 수용하기에 기능이 너무 부족하다.(사실 이 글을 작성하게 된 계기도 사용자의 자동완성 기능 구현 요구 때문이었다.^^) 이런 select 엘러먼트의 부족한 기능을 강화시켜주는 애드온 성격의 라이브러리가 많은데 이번 글에서는 많이 사용되는 Select2 라이브러리의 기본적인 사용법을 설명하고자 한다.

Select2 특징

본격적으로 사용법을 정리하기에 앞서 Select2 라이브러리의 기본적인 특징은 아래와 같다.

  • 자동완성(AutoComplete)AJAX를 이용한 원격 데이터 불러오기가 가능하다. 자동완성의 경우 한글은 문자 단위부터 가능하며 초성은 지원되지 않는다.
  • jQuery 기반의 플러그인으로 jQuery가 필수이다.
  • Bootstrap 테마를 지원하여 위화감 없이 사용이 가능하다.
  • GPL v2 라이센스이다. 상업적인 목적의 수정이 아닌 이상 무료 사용이 가능하다.

라이브러리 로드

Select2 라이브러리는 아래와 같이 로드한다. 아래는 예를 보여주기 위해 공식 홈페이지의 경로에서 바로 로드하였는데 프로젝트에 사용할 경우 압축 파일을 다운로드하여 적절한 위치에 저장 후 임포트해서 사용하도록 한다.

<link href="https://ivaynberg.github.io/select2/select2-3.5.1/select2.css" rel="stylesheet"/>
<script src="https://ivaynberg.github.io/select2/select2-3.5.1/select2.js"></script>

기본 사용법

Select2(v3.5.1 기준) 라이브러리의 기본적인 사용 방법은 아래와 같다. 가장 먼저 HTML에 출력될 부분을 선언한다.

<div id="someSelect"></div>
  • HTML 상에서 사용자에게 출력될 데이터를 명시하지 않고 JavaScript 상에서 원격 데이터를 로드하려면 select 엘러먼트를 사용하지 말고 div 엘러먼트를 사용해야 한다.

JavaScript 상에서는 아래와 같이 초기화한다.

// 원격 데이터를 부여하여 select 엘러먼트를 초기화한다. 이 작업으로 기본 셋업은 끝났다.
var data = [{
  id: 'KOR',
  text: 'Korea'
}, {
  id: 'JPN',
  text: 'Japan'
}];

$('#someSelect').select2({
  data: data,
  width: '100%'
});
  • data는 배열 형태로 각 배열의 요소는 idtext를 가진 오브젝트이어야 한다.
  • width는 화면에 출력될 Select 엘러먼트의 크기로 픽셀 또는 퍼센트로 지정이 가능하다.
실행 결과는 아래와 같다. 자동완성(AutoComplete) 기능이 적용되는 것을 확인할 수 있다.


선택 값 획득 및 설정하기

// 사용자가 선택한 값을 획득한다. 어떤 값도 선택하지 않았을 경우 ''을 반환한다.
var someValue = $('#someSelect').select2('val');

// select 엘러먼트의 선택 값을 받는 일반적인 방법으로도 획득이 가능하다.
var someValue = $('#someSelect').val();

// 코드 레벨에서 임의의 값을 선택한다.
// 임의의 값 선택시 기존 데이터 배열에 존재하지 않는 값이면 '' 값이 설정된다.
$('#someSelect').select2('val', 'someValue');

비활성화 및 활성화하기

때때로 다른 select 엘러먼트의 결과에 따라 select 엘러먼트를 비활성화하거나 활성화할 필요가 있다. 아래와 같이 코드 레벨에서 비활성화 및 활성화가 가능하다.

// 값을 초기화한다.
$('#someSelect').select2('val', '');
// 비활성화한다.
$('#someSelect').select2('enable', false);
// 활성화한다.
$('#someSelect').select2('enable', true);

// 문서 로드시 처음부터 비활성화된 채로 select 엘러먼트를 초기화해두려면 아래와 같이 작성한다.
$('#someSelect').select2({
  data: [{}],
  width: '100%'
});
$('#someSelect').select2('val', '');
$('#someSelect').select2('enable', false);

// 아래와 같이 jQuery의 플러그인으로 만들 수도 있다. 플러그인을 만드는 방법이 사용에 있어 훨씬 편리하다.
$.fn.select2Disabled = function() {
  $(this).select2({
    data: [{}],
    width: '100%'
  });
  $(this).select2('val', '');
  $(this).select2('enable', false);
};

// 앞서 작성한 비활성화 플러그인을 호출한다.
$('#someSelect').select2Disabled();

// 새로운 데이터를 로드하면서 활성화하는 플러그인도 만들어두면 편리하다. data와 callback 메써드를 매개변수로 두어 확장성을 높였다.
$.fn.select2Enabled = function(data, callback) {
  $(this).select2('val', '');
  $(this).select2('enable', true);
  $(this).select2('destroy');
  $(this).select2({
    data: data,
    width: '100%'
  });
  $(this).on('select2-selecting', callback);
};

한글화

Select2 라이브러리는 기본적으로 한글화 언어팩을 제공하지만 자신만의 커스터마이징된 한글화도 가능하다. 아래는 내가 필요로 하는 문자열만 한글화하였다.

(function($) {
  "use strict";
  $.fn.select2.locales['ko'] = {
    formatNoMatches: function() {
      return "데이터가 없습니다.";
    }
  };
  $.extend($.fn.select2.defaults, $.fn.select2.locales['ko']);
})(jQuery);

그 밖의 팁

가독성을 위해 셀렉트 엘러먼트 클릭시 출력되는 옵션 목록의 글꼴을 고정폭 글꼴로 변경하려면 아래와 같이 CSS를 설정한다.

.select2-result-label {
  font-family: '돋움체' !important;
}

대부분의 경우 Select2의 데이터 소스는 하드 코딩보다는 원격 데이터베이스에서 쿼리 결과를 바인딩하는 형태로 사용한다. 데이터 바인딩을 돕는 유틸리티 오브젝트를 아래와 같이 만들어봤다.

// Select2Util은 Select2를 보완하는 유틸리티 오브젝트이다.
var Select2Util = {
  // 1개 컬럼(id) 또는 2개 컬럼(1번째 컬럼은 id, 2번째 컬럼은 text) 구조를 가진 원격 데이터 배열을 Select2의 원격 소스로 사용되는 data 형식으로 변경한다.
  // 멀티 컬럼을 지원하지 않는 단점을 보완하기 위해 text에 id 값을 포함하도록 가공한다.
  //
  // ex) KEY  VALUE  ->  id   text
  //     ----------      ----------------
  //     KOR  Korea      KOR  [KOR] Korea
  //     JPN  Japan      JPN  [JPN] Japan
  //
  // ex) var data = Select2Util.toData(anyData);
  //
  toData: function(data) {
    if (!Array.isArray(data)) {
      return new Array();
    }
    if (data.length === 0) {
      return new Array();
    }
    var keyNames = Object.getOwnPropertyNames(data[0]);
    if (keyNames.length > 2) {
      return new Array();
    }
    var id = keyNames[0];
    var text = keyNames[0];
    if (keyNames.length == 2) {
      text = keyNames[1];  
    }
    var newData = new Array();
    for (var i = 0; i < data.length; i++) {
      var newObject = {};
      newObject['id'] = data[i][id];
      newObject['text'] = data[i][text];
      if (keyNames.length == 2) {  
        newObject['text'] = '[' + data[i][id] + '] ' + data[i][text];
      }
      newData.add(newObject);
    }
    return newData;
  },
  // Select2의 원격 소스로 사용되는 data 배열에 새로운 오브젝트를 추가한다.
  //
  // ex) Select2Util.addData(oldData, {id : 'CHN', text: 'CHINA');
  //
  addData: function(data, newData) {
    var object = data.find(function(n) {
      return n['id'] == newData['id'];
    });
    if (typeof object === 'undefined') {
      data.add({
        id: newData['id'],
        text: '[' + newData['id'] + '] ' + newData['text']
      });
    }
    return data;
  }
};


저작자 표시 비영리 동일 조건 변경 허락
신고