Ajax로 Select2 4.0.0 초기 값


98

Ajax 배열에서 select2 v4.0.0이 채워집니다. select2의 val을 설정하면 javascript 디버깅을 통해 올바른 항목 (제 경우 # 3)을 선택했음을 알 수 있지만 선택 상자에 표시되지 않지만 여전히 자리 표시자를 표시합니다. 여기에 이미지 설명 입력

나는 다음과 같은 것을보아야합니다. 여기에 이미지 설명 입력

내 양식 필드에서 :

<input name="creditor_id" type="hidden" value="3">
<div class="form-group minimal form-gap-after">
    <span class="col-xs-3 control-label minimal">
        <label for="Creditor:">Creditor:</label>
    </span>
    <div class="col-xs-9">
        <div class="input-group col-xs-8 pull-left select2-bootstrap-prepend">
            <select class="creditor_select2 input-xlarge form-control minimal select2 col-xs-8">
                <option></option>
            </select>
        </div>
    </div>
</div>

내 자바 스크립트 :

var initial_creditor_id = "3";
$(".creditor_select2").select2({
    ajax: {
       url: "/admin/api/transactions/creditorlist",
       dataType: 'json',
       delay: 250,
       data: function (params) {
           return {
                q: params.term,
                c_id: initial_creditor_id,
                page: params.page
           };
       },
       processResults: function (data, page) {
            return {
                results: data
            };
       },
       cache: true
   },
   placeholder: "Search for a Creditor",
   width: "element",
   theme: "bootstrap",
   allowClear: true
   }).on("select2:select", function (e) {
      var selected = e.params.data;
      if (typeof selected !== "undefined") {
           $("[name='creditor_id']").val(selected.creditor_id);
           $("#allocationsDiv").hide();
           $("[name='amount_cash']").val("");
           $("[name='amount_cheque']").val("");
           $("[name='amount_direct']").val("");
           $("[name='amount_creditcard']").val("");
        }
    }).on("select2:unselecting", function (e) {
        $("form").each(function () {
            this.reset()
        });
        ("#allocationsDiv").hide();
        $("[name='creditor_id']").val("");
    }).val(initial_creditor_id);

선택 상자에 자리 표시자가 아닌 선택한 항목이 표시되도록하려면 어떻게해야합니까? AJAX JSON 응답의 일부로 이것을 보내야합니까?

과거에 Select2에는 사용자 지정 데이터 소스를 사용할 때마다 정의 된 initSelection이라는 옵션이 필요했기 때문에 구성 요소에 대한 초기 선택을 결정할 수있었습니다. 이것은 v3.5에서 잘 작동했습니다.


어떻게 가능합니까? 내가 바인드 select를 시도 할 때 ajax오류가 발생하면 해당 옵션 ajax는 select와 함께 사용할 수 없습니다.
Daggeto

답변:


109

대부분의 작업을 올바르게 수행하고 change있으며, 새 값을 설정 한 후 메서드를 트리거하지 않는 것이 유일한 문제인 것처럼 보입니다 . change이벤트가 없으면 Select2는 기본 값이 변경되었음을 알 수 없으므로 자리 표시 자만 표시합니다. 마지막 부분을

.val(initial_creditor_id).trigger('change');

문제를 해결하고 UI 업데이트를 즉시 확인해야합니다.


이것은 당신이 가지고 있다고 가정한다 <option>가지고 이미 valueinitial_creditor_id. Select2를 수행하지 않으면 브라우저는 전환 할 옵션이 없기 때문에 실제로 값을 변경할 수 없으며 Select2는 새 값을 감지하지 않습니다. <select>자리 표시 자에 대한 옵션이 하나뿐 이라는 것을 알게되었습니다. 즉 , 새 옵션을 <option>수동으로 만들어야합니다 .

var $option = $("<option selected></option>").val(initial_creditor_id).text("Whatever Select2 should display");

그런 다음 <select>Select2를 초기화 한에 추가하십시오 . 외부 소스에서 텍스트를 가져와야 할 수도 있습니다. 외부 소스는 initSelection사용하던 곳 이며 Select2 4.0.0에서도 여전히 가능합니다. 표준 선택과 마찬가지로 이는 값을 검색하기 위해 AJAX 요청을 한 다음 <option>조정을 위해 즉시 텍스트 를 설정해야 함 을 의미합니다.

var $select = $('.creditor_select2');

$select.select2(/* ... */); // initialize Select2 and any events

var $option = $('<option selected>Loading...</option>').val(initial_creditor_id);

$select.append($option).trigger('change'); // append the option and update Select2

$.ajax({ // make the request for the selected data object
  type: 'GET',
  url: '/api/for/single/creditor/' + initial_creditor_id,
  dataType: 'json'
}).then(function (data) {
  // Here we should have the data object
  $option.text(data.text).val(data.id); // update the text that is displayed (and maybe even the value)
  $option.removeData(); // remove any caching data that might be associated
  $select.trigger('change'); // notify JavaScript components of possible changes
});

이것은 많은 코드처럼 보일 수 있지만 모든 변경이 이루어 졌는지 확인하기 위해 Select2가 아닌 선택 상자에 대해 정확히 수행하는 방법 입니다.


14
다중 선택 상자에 대해 여러 옵션을 미리 선택하는 방법을 알고 있습니까?
user396404

6
@ user396404 동일한 개념이 적용되어야 val()하며 단일 ID 대신 ID 목록을 전달하면됩니다 . 또는 여러 개를 추가하면 <option selected>자동으로 처리됩니다.
Kevin Brown

5
이 답변은 1 년이 넘었지만 FAQ 질문에 대한 Select2 문서 : "AJAX를 사용할 때 처음 선택한 옵션을 어떻게 설정할 수 있습니까?" 여전히 이것을 가리 킵니다. 나는 v4.0.3에 대한 작업 예제로 JSFiddle을 첨부했습니다 jsfiddle.net/57co6c95
클린트

2
문제가 있습니다. 아이디와 텍스트 이상의 것을 요청하려면 어떻게해야합니까? 시도했지만 데이터 옵션은 templateResult에 대한 데이터 만 가져오고 templateSelection에 대해서는 무시합니다. 어떤 생각?
ClearBoth

2
또한이 솔루션을 시도했지만 불행히도 $select.trigger('change');옵션 을 호출 한 후에도 원하는 텍스트가 정확히 있었음에도 불구하고 여전히 Loading ... 텍스트 data.text가 있습니다. 4.0.6 에서 더 이상 지원되지 않을 수 있습니다.
Alisson

29

내가 한 일은 더 깨끗하고 두 개의 배열을 만들어야합니다.

  • 하나는 id와 텍스트가있는 Object 목록을 포함합니다 (내 경우에는 templateResult에 따라 ID와 이름) (Ajax 쿼리에서 얻은 것)
  • 두 번째는 ID 배열 (선택 값) 일뿐입니다.

첫 번째 배열을 데이터로 사용하고 두 번째 배열을 val로 사용하여 select2를 초기화합니다.

id : name의 dict를 매개 변수로 사용하는 예제 함수입니다.

function initMyList(values) {
    var selected = [];
    var initials = [];

    for (var s in values) {
        initials.push({id: s, name: values[s].name});
        selected.push(s);
    }

    $('#myselect2').select2({
        data: initials,
        ajax: {
            url: "/path/to/value/",
            dataType: 'json',
            delay: 250,
            data: function (params) {
                return {
                    term: params.term,
                    page: params.page || 1,
                };
            },
            processResults: function (data, params) {
                params.page = params.page || 1;

                return {
                    results: data.items,
                    pagination: {
                        more: (params.page * 30) < data.total_count
                    }
                };
            },
            cache: true
        },
        minimumInputLength: 1,
        tokenSeparators: [",", " "],
        placeholder: "Select none, one or many values",
        templateResult: function (item) { return item.name; },
        templateSelection: function (item) { return item.name; },
        matcher: function(term, text) { return text.name.toUpperCase().indexOf(term.toUpperCase()) != -1; },
    });

    $('#myselect2').val(selected).trigger('change');
}

ajax 호출을 사용하여 이니셜 값을 제공하고 jquery promise를 사용하여 select2 초기화를 수행 할 수 있습니다.


3
이것은 확실히 더 나은 방법입니다. DOM을 추가하여 조작하는 <option>것이 가장 논리적 인 방법은 아닌 것 같습니다. 이것이 제가 4.0에서하는 방법입니다
jiaweizhang

2
@ firebird631, 귀하의 솔루션은 훌륭하며 작동하며 매우 감사합니다!
userlond

이것은 내가 지금까지 본 가장 깨끗한 솔루션입니다
지미 Ilenloa

내부적으로 data옵션은 <option>태그를 생성 하고 선택 항목에 추가하는 것입니다. 이 답변은 더 많은 정보를 얻기 위해 API로 이동해야하는 경우를 처리하는 방법을 다루지 않지만 덜 일반적인 경우라고 생각합니다.
Kevin Brown

안녕하세요 ajax로 할 수 없습니다. 두 개의 개체가있는 목록을 보낼 때 두 개체를 삽입하려고 시도하지만 하나만 삽입하는 데 문제가 없습니다. 이미 자동으로 선택되었습니다. 두 가지 항목을 보냈 는데도 두 가지 옵션이 보이지 않습니다.
Sahin Yanlık

7

그것은 나를 위해 작동합니다 ...

jQuery를 사용하지 말고 HTML 만 사용 : 선택한 대로 표시 할 옵션 값 을 만듭니다 . ID가 select2 데이터에 있으면 자동으로 선택됩니다.

<select id="select2" name="mySelect2">
  <option value="mySelectedValue">
        Hello, I'm here!
  </option>
</select>

Select2.org-기본 사전 선택된 값


6

사용자가 드롭 다운에서 옵션을 변경할 때만 트리거되어야 trigger('change')하는 change트리거에 사용자 지정 코드가 있었기 때문에 강제로 나를 미치게 하는 문제입니다 . IMO, 시작시 초기화 값을 설정할 때 변경이 트리거되지 않아야합니다.

나는 깊이 파고 다음을 발견했다 : https://github.com/select2/select2/issues/3620

예:

$dropDown.val(1).trigger('change.select2');


4

사람들이 실제로 대답하는 것을 보지 못한 한 가지 시나리오는 옵션이 AJAX 소스 일 때 미리 선택하는 방법이며 여러 개를 선택할 수 있습니다. AJAX 사전 선택을위한 이동 페이지이므로 여기에 솔루션을 추가하겠습니다.

$('#mySelect').select2({
    ajax: {
        url: endpoint,
        dataType: 'json',
        data: [
            { // Each of these gets processed by fnRenderResults.
                id: usersId,
                text: usersFullName,
                full_name: usersFullName,
                email: usersEmail,
                image_url: usersImageUrl,
                selected: true // Causes the selection to actually get selected.
            }
        ],
        processResults: function(data) {

            return {
                results: data.users,
                pagination: {
                    more: data.next !== null
                }
            };

        }
    },
    templateResult: fnRenderResults,
    templateSelection: fnRenderSelection, // Renders the result with my own style
    selectOnClose: true
}); 

3

templateSelection 및 ajax를 사용하는 경우 이러한 다른 답변 중 일부가 작동하지 않을 수 있습니다. 새로운 만드는 것 같다 option요소와 설정 valuetext데이터 객체 ID와 텍스트 이외의 값을 사용할 때 템플릿 방법을 만족하지 않습니다.

나를 위해 일한 것은 다음과 같습니다.

$("#selectElem").select2({
  ajax: { ... },
  data: [YOUR_DEFAULT_OBJECT],
  templateSelection: yourCustomTemplate
} 

여기에서 jsFiddle을 확인하세요 : https://jsfiddle.net/shanabus/f8h1xnv4

제 경우 processResults에는 데이터에 필수 idtext필드가 포함되지 않았기 때문에 입력해야했습니다 . 이 작업을 수행해야하는 경우 동일한 기능을 통해 초기 선택을 실행해야합니다. 이렇게 :

$(".js-select2").select2({
  ajax: {
    url: SOME_URL,
    processResults: processData
  },
  data: processData([YOUR_INIT_OBJECT]).results,
  minimumInputLength: 1,
  templateSelection: myCustomTemplate
});

function processData(data) {
  var mapdata = $.map(data, function (obj) {      
    obj.id = obj.Id;
    obj.text = '[' + obj.Code + '] ' + obj.Description;
    return obj;
  });
  return { results: mapdata }; 
}

function myCustomTemplate(item) {
     return '<strong>' + item.Code + '</strong> - ' + item.Description;
}

드디어!!!!! 와우, 이보다 더 답답할 수는 없습니다 !! 나는 "텍스트"대신 "이름"을 사용하고 있었고 그것은 나를 죽이고 있었다. 기본 "텍스트"키로 전환했는데 이제 완벽하게 작동합니다. 감사합니다!
HTMLGuy

1

해결책을 찾기 위해 몇 시간을 보낸 후, 저는 저만의 솔루션을 만들기로 결정했습니다. 그는 :

 function CustomInitSelect2(element, options) {
            if (options.url) {
                $.ajax({
                    type: 'GET',
                    url: options.url,
                    dataType: 'json'
                }).then(function (data) {
                    element.select2({
                        data: data
                    });
                    if (options.initialValue) {
                        element.val(options.initialValue).trigger('change');
                    }
                });
            }
        }

그리고이 함수를 사용하여 선택을 초기화 할 수 있습니다.

$('.select2').each(function (index, element) {
            var item = $(element);
            if (item.data('url')) {
                CustomInitSelect2(item, {
                    url: item.data('url'),
                    initialValue: item.data('value')
                });
            }
            else {
                item.select2();
            }
        });

물론 다음은 html입니다.

<select class="form-control select2" id="test1" data-url="mysite/load" data-value="123"></select>

일반적인 초기화 절차에 대한 좋은 아이디어입니다.
Carlos Mora

1

간단하고 의미 론적 솔루션의 경우 HTML에서 초기 값을 정의하는 것을 선호합니다. 예 :

<select name="myfield" data-placeholder="Select an option">
    <option value="initial-value" selected>Initial text</option>
</select>

그래서 내가 호출 $('select').select2({ ajax: {...}});하면 초기 값은 initial-value이고 옵션 텍스트는 Initial text.

내 현재 Select2 버전은 4.0.3 이지만 다른 버전과의 호환성 이 뛰어나다 고 생각합니다.


선택 값뿐만 아니라 텍스트도 데이터베이스에 저장하고있는 것 같습니다. 이렇게 검색 할 수 있습니다. 쉿!
ITDesigns.eu

@ ITDesigns.eu, 저는 그렇게 생각하지 않습니다. 데이터베이스에 대한 센토 값은 initial-value있고 텍스트 Initial text가 자리 표시 자 역할을하므로 데이터베이스로 보내지지 않습니다. 내 응용 프로그램에서 작동합니다.
Marcio Mazzucato

실제 옵션에서 실제 텍스트 대신 자리 표시자가 필요한 이유는 무엇입니까?!
ITDesigns.eu

ITDesigns.eu @, 선택 2는이 정보를 잡는다 자체를 마운트
마르 Mazzucato

1

https://github.com/select2/select2/issues/4272 이것 만으로 문제가 해결되었습니다. 옵션으로 기본값을 설정하더라도 텍스트 속성이있는 개체의 형식을 지정해야하며 이것이 옵션에 표시하려는 것입니다. 따라서 형식 함수는 ||비어 있지 않은 속성을 선택하는 데 사용해야 합니다.


0

나는 위에서 언급 할 수 없기 때문에 주로이 답변을 추가하고 있습니다! @Nicki와 그녀의 jsfiddle, https://jsfiddle.net/57co6c95/ 의 댓글 이 결국 나를 위해 작동한다는 것을 알았 습니다.

무엇보다도 필요한 json에 대한 형식의 예를 제공했습니다. 내가 변경해야 할 유일한 변경 사항은 초기 결과가 다른 ajax 호출과 동일한 형식으로 반환되었으므로 사용해야했습니다.

$option.text(data[0].text).val(data[0].id);

보다는

$option.text(data.text).val(data.id);

0

select2 4.0.3에 대한 초기 선택 값으로 간단한 아약스 콤보 만들기

<select name="mycombo" id="mycombo""></select>                   
<script>
document.addEventListener("DOMContentLoaded", function (event) {
    selectMaker.create('table', 'idname', '1', $("#mycombo"), 2, 'type');                                
});
</script>  

라이브러리 .js

var selectMaker = {
create: function (table, fieldname, initialSelected, input, minimumInputLength = 3, type ='',placeholder = 'Select a element') {
    if (input.data('select2')) {
        input.select2("destroy");
    }
    input.select2({
        placeholder: placeholder,
        width: '100%',
        minimumInputLength: minimumInputLength,
        containerCssClass: type,
        dropdownCssClass: type,
        ajax: {
            url: 'ajaxValues.php?getQuery=true&table=' + table + '&fieldname=' + fieldname + '&type=' + type,
            type: 'post',
            dataType: 'json',
            contentType: "application/json",
            delay: 250,
            data: function (params) {
                return {
                    term: params.term, // search term
                    page: params.page
                };
            },
            processResults: function (data) {
                return {
                    results: $.map(data.items, function (item) {
                        return {
                            text: item.name,
                            id: item.id
                        }
                    })
                };
            }
        }
    });
    if (initialSelected>0) {
        var $option = $('<option selected>Cargando...</option>').val(0);
        input.append($option).trigger('change'); // append the option and update Select2
        $.ajax({// make the request for the selected data object
            type: 'GET',
            url: 'ajaxValues.php?getQuery=true&table=' + table + '&fieldname=' + fieldname + '&type=' + type + '&initialSelected=' + initialSelected,
            dataType: 'json'
        }).then(function (data) {
            // Here we should have the data object
            $option.text(data.items[0].name).val(data.items[0].id); // update the text that is displayed (and maybe even the value)
            $option.removeData(); // remove any caching data that might be associated
            input.trigger('change'); // notify JavaScript components of possible changes
        });
    }
}
};

그리고 PHP 서버 측

<?php
if (isset($_GET['getQuery']) && isset($_GET['table']) && isset($_GET['fieldname'])) {
//parametros carga de petición
parse_str(file_get_contents("php://input"), $data);
$data = (object) $data;
if (isset($data->term)) {
    $term = pSQL($data->term);
}else{
    $term = '';
}
if (isset($_GET['initialSelected'])){
    $id =pSQL($_GET['initialSelected']);
}else{
    $id = '';
}
if ($_GET['table'] == 'mytable' && $_GET['fieldname'] == 'mycolname' && $_GET['type'] == 'mytype') {

    if (empty($id)){
        $where = "and name like '%" . $term . "%'";
    }else{
         $where = "and id= ".$id;
    }

    $rows = yourarrayfunctionfromsql("SELECT id, name 
                    FROM yourtable
                    WHERE 1 " . $where . "
                    ORDER BY name ");
}

$items = array("items" => $rows);
$var = json_encode($items);
echo $var;
?>

-4

안녕하세요, 거의 종료하고 3.5.1을 선택합니다. 그러나 마침내 나는 답을 얻었다!

$('#test').select2({
    placeholder: "Select a Country",
    minimumResultsForSearch: 2,
    ajax: {
        url: '...',
        dataType: 'json',
        cache: false,
        data: function (params) {
                var queryParameters = {
                    q: params.term
                }
                return queryParameters;
        },
        processResults: function (data) {
            return {
                results: data.items
            };
        }
    }
});

var option1 = new Option("new",true, true);

$('#status').append(option1);

$('#status').trigger('change');

새 옵션이 select2 옵션 중 하나인지 확인하십시오. 나는 이것을 json으로 얻습니다.


안녕하세요. '#status'가 무엇인가요? '#test'여야합니까?
user2808054
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.