web-dev-qa-db-fra.com

Choisi: Garder l'ordre de sélection multiple

J'utilise la sélection multiple de Chosen. Je veux pouvoir suivre la commande sélectionnée par l'utilisateur. Par exemple, si un utilisateur sélectionne d'abord l'option2, puis l'option1, je souhaite obtenir le résultat dans l'ordre indiqué par option2 et option1. Mais choisi trie les options sélectionnées par l'utilisateur. Y at-il un moyen que je peux dire choisi de ne pas trier le résultat?

24
topcan5

J'ai écrit un plugin simple à utiliser avec Chosen. Il vous permet de récupérer l'ordre de sélection d'un élément de sélection multiple choisi, ainsi que de le définir à partir d'un tableau de valeurs ordonnées.

Il est disponible sur Github: https://github.com/tristanjahier/chosen-order

Il est compatible avec Chosen 1.0+ et avec les versions jQuery et Prototype. Il existe également un plugin pour chaque framework, qui vous permet de faire des choses comme ceci:

Récupérer l'ordre de sélection

var selection = $('#my-list').getSelectionOrder();

Définir les valeurs sélectionnées dans l'ordre

var order = ['nioup', 'plop', 'fianle']; // Ordered options values
$('#my-list').setSelectionOrder(order);

Vérifiez-le.

12
Tristan Jahier

Il existe un https://github.com/mrhenry/jquery-chosen-sortable/ plugin maintenant disponible, qui fait le travail pour la v1 choisie.

Pour les versions plus récentes de selected, vous devez remplacer chzn- par selected- dans le fichier github JS.

Pour l'utiliser, j'utilise le code suivant:

jQuery('#myselect').addClass('chosen-sortable').chosenSortable();

Cela fonctionne très bien, mais vous aurez besoin de plus de code lors de la modification du champ pour réorganiser les éléments après le choix.

J'utilise ce qui suit pour cela. Étant donné la liste des éléments sortis et $ select = jQuery ('# myselect'):

var $container = $select.siblings('.chosen-container')
var $list = $container.find('.chosen-choices');

// Reverse the list, as we want to prepend our elements.
var sortedElements = sortedElements.reverse();

for (var i = 0; i < sortedElements.length; i++) {
  var value = sortedElements[i];

  // Find the index of the element.
  var index = $select.find('option[value="' + value + '"]').index();

  // Sort the item first.
  $list
          .find('a.search-choice-close[data-option-array-index="' + index + '"]')
          .parent()
          .remove()
          .prependTo($list);
}

Cela fonctionne très bien ici.

4
LionsAd

Je vous suggère d'utiliser Select2 s'il n'est pas trop tard. Il ressemble à Chosen mais possède une API et une documentation bien meilleures. 

Avec select2, ce serait quelque chose comme [code non testé]

 var results = [];
 $("#e11").on("change", function(e) { 
    results.Push(e.val)
 })
4
Aktee

Vous pouvez ajouter/supprimer des éléments vous-même lors d'un événement de changement.

// Your collection Array
var collectionArray = [] 

// make change event on chosen select field
chosenSelect.change(function () {
  // first get the chosen results which might be in wrong order
  var currentValues = $(this).val();

  // get your current collection that is in the right order
  var pastValues = collectionArray;

  // see if you need to add or drop
  if (currentValues.length > pastValue.length) {

    // loop to get just the new item
    pastValues.forEach(function(pastValue) {
      currentValue = $.grep(currentValue, function(newItemOnly) {
        return newItemOnly != pastValue;
      });
    });

    // add your newItemOnly
    collectionArray.Push(currentValue[0]);

  } else {

    // here loop to get only the dropped value
    currentValues.forEach(function(currentValue) {
      pastValues = $.grep(pastValues, function(droppedValueOnly) {
        return droppedValueOnly != currentValue;
      });
    });

    // drop the value dropped from your collection
    collectionArray = $.grep(collectionArray, function(updatedArray) {
      return updatedArray != pastValues[0];
    });
  }
});
1
Michael Wiltbank

J'ai injecté un gestionnaire d'événements .change() personnalisé pour le faire fonctionner:

$('.chosen-select').chosen({});

à:

$('.chosen-select').chosen({}).change((event, info) => {
  if (info.selected) {
    var allSelected = this.querySelectorAll('option[selected]');
    var lastSelected = allSelected[allSelected.length - 1];
    var selected = this.querySelector(`option[value="${info.selected}"]`);
    selected.setAttribute('selected', '');
    lastSelected.insertAdjacentElement('afterEnd', selected);
  } else { // info.deselected
    var removed = this.querySelector(`option[value="${info.deselected}"]`);
    removed.setAttribute('selected', false); // this step is required for Edge
    removed.removeAttribute('selected');
  }
  $(this).trigger("chosen:updated");
});

Notez que cela déplace le DOM en cas de sélection et aucun mouvement en cas de désélection. La setAttribute/removeAttribute doit provoquer un changement visible dans <option> DOM.

J'espère que cela aidera quelqu'un qui cherche encore un moyen de le faire sans rien faire de plus lors de la soumission.

PS: la version jQuery compacte de ce code peut être écrite si nécessaire. :)

0
vulcan raven

J'espère que cela sera utile aux personnes utilisant une version antérieure de select2 (inférieure à v4). select2-selection et select2-remove options sont utiles dans ce cas. En utilisant un tableau et en ajoutant les valeurs une fois que nous avons sélectionné, nous pouvons conserver l'ordre de sélection et tout en désélectionnant une option particulière, nous pouvons rechercher l'index et le supprimer du tableau à l'aide de splice ().

var selected = [];    
$('#multiSelect').on("select2-selecting", function(evt) {
            var selectedOption = evt.val;
            selected.Push(selectedOption);

        }).on("select2-removing", function(evt) {
              index = selected.indexOf(evt.val);
              selected.splice(index,1);       
        });   

Pour les versions 4 et supérieures, sélectionnez 2: sélectionnez et sélectionnez 2: désélectionnez peut être utilisé. :)

0
Mounika Sai