jquery-select2-4 - all - select2 response
Select2 4.0.0 valor inicial con Ajax (12)
¡Estoy agregando esta respuesta principalmente porque no puedo comentar arriba! Descubrí que fue el comentario de @Nicki y su jsfiddle, jsfiddle.net/57co6c95 , lo que finalmente hizo que esto funcionara para mí.
Entre otras cosas, dio ejemplos del formato para el json necesario. El único cambio que tuve que hacer fue que mis resultados iniciales fueron devueltos en el mismo formato que la otra llamada ajax, así que tuve que usar
$option.text(data[0].text).val(data[0].id);
más bien que
$option.text(data.text).val(data.id);
Tengo un select2 v4.0.0 que se completa desde una matriz Ajax. Si configuro el valor de select2, puedo ver a través de la depuración de JavaScript que ha seleccionado el elemento correcto (# 3 en mi caso), sin embargo, esto no se muestra en el cuadro de selección, todavía muestra el marcador de posición.
Mientras que debería estar viendo algo como esto:
En mis campos de formulario:
<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>
Mi 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);
¿Cómo puedo hacer que el cuadro de selección muestre el elemento seleccionado en lugar del marcador de posición? ¿Debería enviar esto como parte de la respuesta AJAX JSON, tal vez?
En el pasado, Select2 requería una opción llamada initSelection que se definía cada vez que se usaba una fuente de datos personalizada, lo que permitía determinar la selección inicial del componente. Esto funcionó bien para mí en v3.5.
A mí me funciona ...
No use jQuery, solo HTML: cree el valor de la opción que mostrará como seleccionado . Si la ID está en los datos de select2 , se seleccionará automáticamente.
<select id="select2" name="mySelect2">
<option value="mySelectedValue">
Hello, I''m here!
</option>
</select>
Cree un combo simple de ajax con el valor inicial seleccionado para 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>
biblioteca .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
});
}
}
};
y el lado del servidor 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;
?>
Después de pasar unas horas buscando una solución, decidí crear la mía. El es:
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'');
}
});
}
}
Y puede inicializar las selecciones usando esta función:
$(''.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();
}
});
Y, por supuesto, aquí está el html:
<select class="form-control select2" id="test1" data-url="mysite/load" data-value="123"></select>
El problema de ser forzado a
trigger(''change'')
me volvió loco, ya que tenía un código personalizado en el activador de
change
, que solo debería activarse cuando el usuario cambia la opción en el menú desplegable.
En mi opinión, el cambio no debe activarse al establecer un valor de inicio al comienzo.
Cavé profundamente y encontré lo siguiente: https://github.com/select2/select2/issues/3620
Ejemplo:
$dropDown.val(1).trigger(''change.select2'');
Está haciendo la mayoría de las cosas correctamente, parece que el único problema que está enfrentando es que no está activando el método de
change
después de establecer el nuevo valor.
Sin un evento de
change
, Select2 no puede saber que el valor subyacente ha cambiado, por lo que solo mostrará el marcador de posición.
Cambiando tu última parte a
.val(initial_creditor_id).trigger(''change'');
Debería solucionar su problema y debería ver la actualización de la interfaz de usuario de inmediato.
Esto supone que ya tiene una
<option>
que tiene un
value
de
initial_creditor_id
.
Si no selecciona Select2, y el navegador, en realidad no podrá cambiar el valor, ya que no hay opción para cambiar, y Select2 no detectará el nuevo valor.
Noté que su
<select>
solo contiene una única opción, la del marcador de posición, lo que significa que deberá crear la nueva
<option>
manualmente.
var $option = $("<option selected></option>").val(initial_creditor_id).text("Whatever Select2 should display");
Y luego añádalo al
<select>
que inicializó Select2.
Es posible que necesite obtener el texto de una fuente externa, que es donde solía entrar en juego
initSelection
, que todavía es posible con Select2 4.0.0.
Al igual que una selección estándar, esto significa que tendrá que hacer la solicitud AJAX para recuperar el valor y luego configurar el texto
<option>
sobre la marcha para ajustar.
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
});
Si bien esto puede parecer mucho código, así es exactamente como lo haría para los cuadros de selección que no son de Select2 para asegurarse de que se realizaron todos los cambios.
Hola, casi estaba saliendo de esto y volví a seleccionar 3.5.1. ¡Pero finalmente obtuve la respuesta!
$(''#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'');
Solo asegúrese de que la nueva opción sea una de las opciones select2. Me llega esto por un json.
Lo que he hecho es más limpio y necesita hacer dos matrices:
- uno contiene una lista de objetos con id y un texto (en mi caso, su id y nombre, dependiendo de su templateResult) (es lo que obtiene de la consulta ajax)
- el segundo es solo una matriz de identificadores (valor de selección)
Inicializo select2 usando la primera matriz como datos, y la segunda como val.
Una función de ejemplo con como parámetros un dict de id: nombre.
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'');
}
Puede alimentar el valor de las iniciales usando llamadas ajax y usar jquery promete hacer la inicialización select2.
Para una solución simple y semántica, prefiero definir el valor inicial en HTML, por ejemplo:
<select name="myfield" data-placeholder="Select an option">
<option value="initial-value" selected>Initial text</option>
</select>
Entonces, cuando llamo a
$(''select'').select2({ ajax: {...}});
el valor inicial es valor
initial-value
y su texto de opción es
Initial text
.
Mi versión actual de Select2 es 4.0.3 , pero creo que tiene una gran compatibilidad con otras versiones.
Si está utilizando una templateSelection y ajax, algunas de estas otras respuestas pueden no funcionar.
Parece que crear un nuevo elemento de
option
y establecer el
value
y el
text
no satisfará el método de la plantilla cuando los objetos de datos usen otros valores que no sean id y texto.
Esto es lo que funcionó para mí:
$("#selectElem").select2({
ajax: { ... },
data: [YOUR_DEFAULT_OBJECT],
templateSelection: yourCustomTemplate
}
Echa un vistazo a jsFiddle aquí: https://jsfiddle.net/shanabus/f8h1xnv4
En mi caso, tuve que
processResults
ya que mis datos no contenían los campos de
text
y de
id
necesarios.
Si necesita hacer esto, también deberá ejecutar su selección inicial a través de la misma función.
Al igual que:
$(".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;
}
Un escenario que no he visto que la gente realmente responda, es cómo tener una preselección cuando las opciones son de origen AJAX, y puede seleccionar múltiples. Como esta es la página de inicio para la preselección de AJAX, agregaré mi solución aquí.
$(''#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
});
https://github.com/select2/select2/issues/4272
solo esto resolvió mi problema.
incluso si configura el valor predeterminado por opción, debe formatear el objeto, que tiene el atributo de texto y esto es lo que desea mostrar en su opción.
entonces, su función de formato tiene que usar
||
para elegir el atributo que no está vacío.