2014年5月6日火曜日

jQueryプラグイン/Select2でデータが独自のJSONフォーマット時にうまく表示できないことへの対応

目的

先日、JQueryプラグインのSelect2にてAJAX通信(JSON)によるインクリメンタルサーチを実装した時にいろいろハマったのでその対応を記載しておく。

プラグインの公開先
http://ivaynberg.github.io/select2/

元ネタ取得方法の違いによる利用できるHTML要素の違い

ここで若干話はそれますが、このプラグイン使い方が大きくわけて2通りあって、インクリメンタルサーチをする元ネタがHTMLページ表示時に既に決まっている場合と、そうでない場合によって利用できるHTML要素が決まる。

前者:一覧の全内容が既に決まっている場合

例えば、選択リストの表示アイテムとして1000件決まっていてその中でテキストボックスに入力された内容によりインクリメンタルサーチするようなケース。

この場合は利用する要素はSELECT要素。

では後者はどうなのかというと

後者:一覧の全内容が決まっていない場合(AJAX(JSON/JSONP)で取得)

利用する要素はINPUT要素(TYPE="hidden")に限る

僕は公開先ページの説明をよく読まず、まずはここでハマってしまいました。お恥ずかしい…
選択したものがこの要素に格納される。

元ネタのJSONフォーマットが独自の場合の設定

更にこの元ネタをAJAX(JSON/JSONP)で取得してくるのですが、元ネタはいかのようなフォーマットを前提としている為、JSONフォーマットが独自の場合はどの要素が所定のid,text要素に対応するかを指定してあげないといけません。
[
    { id:"aaaa", text:"なにかしらテキスト1" }
    { id:"bbbb", text:"なにかしらテキスト2" }
  ・・・
    { id:"ffffff", text:"なにかしらテキスト3" }
]
指定方法は公開先に記載してある通りで以下のように青字の部分になります。
ハマりどころは赤文字部分のid要素の「id : "IDに対応するハッシュマップのキー"」です。
これ公開先に書いてないんですよねー(いまはわかりませんが…)。
これがないと、セレクトボックスの動作で選択できないということが発生。

$("input[type='hidden']").select2({
    // JSONフォーマットがカスタム時、どの要素がIDに対応するか設定する必要がある
    // これがないと表示はできても選択できなくなる
    id : "IDに対応するハッシュマップのキー",
    placeholder : '何も選択してないよー',
    cache : false,
    quietMillis :100,
    ajax: {
        url: url,
        dataType: 'json',
        data: function (term, page) {
            return {
                q: term,
                page: (page-1),
                pageLimit: 1000,// 最大表示件数
            };
        },
        results: function (data, page) {
            return {
                results: data.ItemList,
                // 既にサーバー側の処理で最大表示件数に対して表示するページはあるか判定しておく
                more: data.MoreData 
            };
        }
    },
    // 一覧を選択した時に設定される値を設定する関数
    formatSelection : function (item) {
        return item.Name;
    },
    // 一覧のテキストとして表示される値を設定する関数
    formatResult: function (item) {
        return item.Name;
    },
    width: "element",
    dropdownAutoWidth: true
    dropdownCssClass: "bigger-select2",
});

元ネタがJSONフォーマット時の初期表示値の設定

あとついでですが、初期表示を設定する方法として「initSelection」を利用しなさいと公開先には記載してありますが、この関数が呼ばれるタイミングは上記で説明したINPUT要素(TYPE="hidden")のvalue属性に値が設定されている場合のみです。つまり、「$("input[type='hidden']").select2・・・」が呼ばれる時点で既にvalue要素に値を設定しないといけません。

以下の例はAJAXにて初回表示時の値を取得している。

$("input[type='hidden']").select2({
    id : "
IDに対応するハッシュマップのキー",
    placeholder : '何も選択してないよー',
    cache : false,
    quietMillis :100,
    // input[hidden]要素のvalue属性に値が入った時した実行されない
    initSelection: function(element, callback) {
        var id = $(element).val();// input[hidden]要素の値
        if (id == null) {
            return;
        }
        $.ajax({
       type: 'get',
       url: url,
               data : {
                    selectedValue: id,
                    hasUnspecified : false
                },
       success: function (data) {
       //成功
                       if (data && data.ItemList && data.ItemList[0]) {
                            callback(data.ItemList[0]);
                       }
       },
       error: function (data) {
       //失敗
       }
        });
    },




いやー、結局、ソース読んでわかりましたよ。

0 件のコメント: