permettre à de nouvelles valeurs avec chosen.js la sélection multiple
-
29-10-2019 - |
Question
Je suis à l'aide de la chosen.js plugin http://harvesthq.github.com/chosen/ avec jQuery pour permettre à l'utilisateur de sélectionner plusieurs options d'un select.Cependant, je veux maintenant être en mesure de les laisser créer des valeurs qui ne sont pas déjà présents - une idée de comment aller à ce sujet?
EDIT:quelque chose de similaire à l'étiquette de sélection/création de la barre serait proche de ce que je suis après
De préférence sans changer ou de modifier le plugin, mais le fera si nécessaire.
Le code:HTML:
<p>Select something</p>
<select name="theSelect[]" multiple="multiple">
<option value="First Option">First Option</option>
<option value="Second Option">Second Option</option>
</select>
Javascript:
$(function(){
$('select').chosen();
});
Donc, si un utilisateur de type "Troisième Option", je tiens à ajouter que la liste et l'avez sélectionné.La valeur et le nom d'affichage sont / seront les mêmes si ce n'est pas une préoccupation
La solution
D'après la documentation, vous pouvez essayer de faire quelque chose comme ceci:
$('select').append('<option>test</option>');
$('select').trigger('liszt:updated');
Comme Tony l'a déclaré dans les commentaires ci-dessous:
"À partir de la version 1.0 dont le déclencheur est maintenant" choisi: mis à jour ". Voir Harvesthq.github.io/ selected / # change-update-events "
Autres conseils
Je suis tombé sur cela à la recherche des mêmes idées. On dirait que c'est une demande de fonctionnalité assez populaire, et quelques fourches l'ont implémentée.Il semble qu'il sera bientôt fusionné dans la branche principale.
+1 pour cette attraction particulière qui a fait un charme: https://github.com/harvesthq/chosen/pull/166
Vous pouvez voir la fourchette de Koenpunt ici: https://github.com/koenpunt/chosen
Voici une façon simple de procéder:
$(".search-field").find("input").live( "keydown", function (evt) {
var stroke;
stroke = (_ref = evt.which) != null ? _ref : evt.keyCode;
if (stroke == 9) { // 9 = tab key
$('#tags').append('<option value="' + $(this).val() + '" selected="selected">' + $(this).val() + '</option>');
$('#tags').trigger('chosen:updated');
}
});
J'essayais juste de résoudre le même problème.J'ai un peu mal en modifiant le code source.Voici la nouvelle fonction keyup_checker.Jetez un coup d'œil à l'affaire 13:
AbstractChosen.prototype.keyup_checker = function(evt) {
var stroke, _ref;
stroke = (_ref = evt.which) != null ? _ref : evt.keyCode;
this.search_field_scale();
switch (stroke) {
case 8:
if (this.is_multiple && this.backstroke_length < 1 && this.choices > 0) {
return this.keydown_backstroke();
} else if (!this.pending_backstroke) {
this.result_clear_highlight();
return this.results_search();
}
break;
case 13:
evt.preventDefault();
if (this.results_showing) {
if (!this.is_multiple || this.result_highlight) {
return this.result_select(evt);
}
$(this.form_field).append('<option>' + $(evt.target).val() + '</option>');
$(this.form_field).trigger('liszt:updated');
this.result_highlight = this.search_results.find('li.active-result').last();
return this.result_select(evt);
}
break;
case 27:
if (this.results_showing) this.results_hide();
return true;
case 9:
case 38:
case 40:
case 16:
case 91:
case 17:
break;
default:
return this.results_search();
}
};
Je sais que ce n'est pas la réponse, mais une solution alternative.
Je cherchais la pièce d'ajout à la volée et j'ai trouvé cela http:// ivaynberg.github.com/select2/#tags fournit la même chose que choisi + d'autres éléments comme "Tagging".
Vous pouvez simplement attacher un événement à la zone de texte d'entrée pour écouter un code de caractère particulier.Après cela, ajoutez l'option et déclenchez la mise à jour dans le menu déroulant.
var dropDown = $('select.chosen');
dropDown.parent().find('.chzn-container .chzn-search input[type=text]').keydown( function (evt) {
var stroke, _ref, target, list;
// get keycode
stroke = (_ref = evt.which) != null ? _ref : evt.keyCode;
target = $(evt.target);
// get the list of current options
list = target.parents('.chzn-container').find('.chzn-choices li.search-choice > span').map(function () { return $(this).text(); }).get();
if (stroke === 9 || stroke === 13) {
var value = $.trim(target.val());
// if the option does not exists
if ($.inArray(value,list) < 0) {
var option = $('<option>');
option.text(value).val(value).appendTo(dropDown);
option.attr('selected','selected');
// add the option and set as selected
}
// trigger the update event
dropDown.trigger("liszt:updated");
return true;
}
});
Une mise à jour de la réponse de leogdion qui fonctionne avec les versions ultérieures de selected:
var dropDown = $('#select_chosen');
// Make the chosen drop-down dynamic. If a given option is not in the list, the user can still add it
dropDown.parent().find('.chosen-container .search-field input[type=text]').keydown(
function (evt) {
var stroke, _ref, target, list;
// get keycode
stroke = (_ref = evt.which) != null ? _ref : evt.keyCode;
// If enter or tab key
if (stroke === 9 || stroke === 13) {
target = $(evt.target);
// get the list of current options
chosenList = target.parents('.chosen-container').find('.chosen-choices li.search-choice > span').map(function () { return $(this).text(); }).get();
// get the list of matches from the existing drop-down
matchList = target.parents('.chosen-container').find('.chosen-results li').map(function () { return $(this).text(); }).get();
// highlighted option
highlightedList = target.parents('.chosen-container').find('.chosen-results li.highlighted').map(function () { return $(this).text(); }).get();
// Get the value which the user has typed in
var newString = $.trim(target.val());
// if the option does not exists, and the text doesn't exactly match an existing option, and there is not an option highlighted in the list
if ($.inArray(newString,matchList) < 0 && $.inArray(newString,chosenList) < 0 && highlightedList.length == 0) {
// Create a new option and add it to the list (but don't make it selected)
var newOption = '<option value="' + newString + '">' + newString + '</option>';
$("#select").prepend(newOption);
// trigger the update event
$("#select").trigger("chosen:updated");
// tell chosen to close the list box
$("#select").trigger("chosen:close");
return true;
}
// otherwise, just let the event bubble up
return true;
}
}
)
J'ai mis à jour le code de 3Nochroot une fois de plus.Maintenant, je n'ai qu'un sélecteur pour trouver l'entrée multisélectionne.
$(document).ready(function() {
$(".js-choicelist").chosen({
//config comes here
}).parent().find('.chosen-container .search-field input[type=text]').keydown(
function (evt) {
var stroke, _ref, target, list;
// get keycode
stroke = (_ref = evt.which) != null ? _ref : evt.keyCode;
// If enter or tab key
if (stroke === 9 || stroke === 13) {
target = $(evt.target);
// get the list of current options
chosenList = target.parents('.chosen-container').find('.chosen-choices li.search-choice > span').map(function () { return $(this).text(); }).get();
// get the list of matches from the existing drop-down
matchList = target.parents('.chosen-container').find('.chosen-results li').map(function () { return $(this).text(); }).get();
// highlighted option
highlightedList = target.parents('.chosen-container').find('.chosen-results li.highlighted').map(function () { return $(this).text(); }).get();
// Get the value which the user has typed in
var newString = $.trim(target.val());
// if the option does not exists, and the text doesn't exactly match an existing option, and there is not an option highlighted in the list
if ($.inArray(newString,matchList) < 0 && $.inArray(newString,chosenList) < 0 && highlightedList.length == 0) {
// Create a new option and add it to the list (but don't make it selected)
var newOption = '<option value="' + newString + '">' + newString + '</option>';
var choiceSelect = target.parents('.select-multiple').find('select');
choiceSelect.prepend(newOption);
// trigger the update event
choiceSelect.trigger("chosen:updated");
// tell chosen to close the list box
choiceSelect.trigger("chosen:close");
return true;
}
// otherwise, just let the event bubble up
return true;
}
}
)
})
Mise à jour de la réponse leogdion pour la sélection multiple ( gist )
$(".chosen-select-with-add-new").chosen({
no_results_text: "Click Enter or Tab to add new option",
width: '100%'
}).parent().find('.chosen-container .search-field input[type=text]').keydown(function (evt) {
// get keycode
const stroke = evt.which != null ? evt.which : evt.keyCode;
// If enter or tab key
if (stroke === 9 || stroke === 13) {
const target = $(evt.target);
// get the list of current options
const chosenList = target.parents('.chosen-container').find('.chosen-choices li.search-choice > span').map(function () { return $(this).text(); }).get();
// get the list of matches from the existing drop-down
const matchList = target.parents('.chosen-container').find('.chosen-results li').map(function () { return $(this).text(); }).get();
// highlighted option
const highlightedList = target.parents('.chosen-container').find('.chosen-results li.highlighted').map(function () { return $(this).text(); }).get();
// Get the value which the user has typed in
const newString = $.trim(target.val());
// if the option does not exists, and the text doesn't exactly match an existing option, and there is not an option highlighted in the list
if ($.inArray(newString, matchList) < 0 && $.inArray(newString,chosenList) < 0 && highlightedList.length == 0) {
// Create a new option and add it to the list (but don't make it selected)
const newOption = '<option value="' + newString + '" selected="selected">' + newString + '</option>';
const choiceSelect = target.parents('.chosen-container').siblings('.chosen-select-with-add-new');
choiceSelect.append(newOption);
// trigger the update event
choiceSelect.trigger("chosen:updated");
// tell chosen to close the list box
choiceSelect.trigger("chosen:close");
return true;
}
// otherwise, just let the event bubble up
return true;
}
})
Exemple d'utilisation sur rails (minces)
.tag-list
label.control-label.h5 Tag list
= select_tag :tag_list, options_for_select(ActsAsTaggableOn::Tag.order('taggings_count desc').pluck(:name), @publication.tags.map(&:name)), multiple: true, data: { placeholder: 'north, east, south, west' }, class: 'chosen-select-with-add-new'
J'ai essayé plusieurs solutions données ici et d'ailleurs, mais aucun n'a travaillé dans chosen.js 1.8.5 (jQuery:3.3.1) et donc j'ai fini avec la suite car je ne voulais pas utiliser une fourchette qui pourrait ne pas toujours être à jour sur la branche master:
Pour le cas que je ne veuille pas tout .chosen-select
pour permettre à de nouvelles valeurs, j'ai ajouté une nouvelle classe .chosen-newValuesAllowed
.J'ai mis un gestionnaire d'événement sur cette classe où CTRL + I ajoute la nouvelle valeur si elle n'est pas encore présente.Le focus sur le champ de saisie ne se perd pas par la suite.Dans mon exemple, j'ai vérifier le innerHTML de la car @valeur réellement contient l'id de base de données et, par conséquent, la nouvelle valeur, ce qui est une chaîne de caractères dans mon exemple, qui seraient traitées par le serveur plus tard, ne pourrait jamais être trouvé dans @valeur.Si vous voulez vérifier @valeur, veuillez voir le commentaire à l'intérieur de l'extrait.Le code traite uniques et multiples sélectionne.
$(document).on("keydown", ".chosen-container.chosen-newValuesAllowed input", function(e) {
if (e.ctrlKey === true && e.keyCode === 73) { // CTRL + I
e.preventDefault();
var newValue = $(this).val();
if (newValue) {
try {
// only add if there is no option having the content/text of "input" yet!
// instead of filter() for the content of <option> you can check on its @value by: find("option[val='...']")
var $selectElement = $(e.target).closest("div.chosen-container").prev(); // the previous sibling should be the <select>. If not, grab it some other way, e.g. via @id
if (!$selectElement.find("option").filter(function () { return $(this).html() === newValue; }).length) {
if (!$selectElement.attr("multiple")) { // unselect for single-select
$selectElement.val('');
}
$selectElement.append('<option val="' + newValue + '" selected>' + newValue + '</option>');
$selectElement.trigger('chosen:updated');
}
} catch(error) {
// pass
}
e.target.focus();
}
return false;
}
});
Une autre solution serait d'appeler la fonction déclenchables choisi:no_results si les nouvelles valeurs ne doivent être ajoutés si explicite est pas le résultat:
$(".chosen-select.chosen-newValuesAllowed").on("chosen:no_results", function(e, data){
var newValue = data.chosen.get_search_text();
...
});