使用Ajax选择2 4.0.0初始值


97

我有一个从Ajax数组填充的select2 v4.0.0。如果我设置了select2的值,则可以通过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>

我的JavaScript:

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中,这对我来说效果很好。


怎么可能?当我尝试selectajax它绑定时出现错误,该选项ajax不允许与select ...
Daggeto

Answers:


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 2015年

6
@ user396404应该应用相同的概念,只是将ID列表传递到val()而不是单个ID中。或者只是追加多个<option selected>,应该自动处理。
凯文·布朗

5
我知道这个答案已经使用了一年多,但是有关FAQ问题的Select2文档:“如何在使用AJAX时设置最初选择的选项?” 仍然指向这一点。我已经附加了JSFiddle作为v4.0.3的工作示例 jsfiddle.net/57co6c95
Clint

2
有一个问题。如果我要请求的不仅仅是ID和文本,该怎么办?我已经尝试过,但是data选项仅获取templateResult的数据,而忽略templateSelection的数据。任何想法?
ClearBoth

2
另外,我尝试了此解决方案,但是不幸的是,在调用$select.trigger('change');该选项之后,即使正好有我想要的文本,仍在“ Loading ...”文本中data.text。也许4.0.6不再支持此功能。
Alisson '18年

28

我所做的是更干净的,需要制作两个数组:

  • 一个包含具有ID和文本的Object列表(在我的情况下,其ID和名称,取决于templateResult)(它是从ajax查询中获得的)
  • 第二个只是一个ID数组(选择值)

我将第一个数组用作数据,将第二个数组用作val来初始化select2。

一个示例函数,其参数为id:name的字典。

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 promises进行select2初始化。


3
这绝对是更好的方法。通过添加来操作DOM <option>似乎并不是最合理的方法。这就是我在4.0中的
做法

2
@ firebird631,您的解决方案很棒,非常有效,非常感谢!
userlond

这是迄今为止我所见过的最干净的解决方案
Jimmy Ilenloa

我将注意到,该data选项仅在内部生成<option>标签并将其添加到选择中。这个答案没有涵盖如何处理需要访问API以获得更多信息的情况,但是我想那是不太典型的情况。
凯文·布朗

您好,ajax我无法做到。当我发送带有两个对象的列表时,没有问题,它尝试插入这两个对象,但只插入了一个。并已自动选择。我从来没有看到两个选项,即使我发送了两个项目。
SahinYanlık17年

7

对我有用...

不使用jQuery,仅使用HTML:创建将显示为selected选项值。如果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,则其他一些答案可能不起作用。当您的数据对象使用除id和text之外的其他值时,似乎创建一个新option元素并设置valuetext不会满足模板方法。

这是对我有用的东西:

$("#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>

通用初始化过程的好主意。
卡洛斯·莫拉

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,我不这样认为,sento发送给数据库的值是initial-value并且文本Initial text充当占位符,它不会发送到数据库。它正在我的应用程序中工作。
Marcio Mazzucato

为什么在实际选项中我需要一个占位符而不是真实文本?
ITDesigns.eu

@ ITDesigns.eu,Select2会捕获此信息并自行安装
Marcio Mazzucato

1

https://github.com/select2/select2/issues/4272 只有这样才能解决我的问题。即使您通过选项设置了默认值,也必须格式化对象,该对象具有text属性,这就是您要在选项中显示的内容。因此,您的format函数必须使用||选择不为空的属性。


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创建具有初始初始值的简单ajax组合

<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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.