web-dev-qa-db-fra.com

Datatables avec des listes déroulantes de filtres de colonnes et une sélection multiple

J'ai trouvé cet excellent code de joao vitor retamero - fiddle: https://jsfiddle.net/jvretamero/bv6g0r64/ qui montre comment effectuer plusieurs sélections dans des filtres de colonne datatable jquery. Mais je dois transformer les conteneurs de filtres en menus déroulants, chaque élément du conteneur constituant une case à cocher. Oui, il y a beaucoup de références à cela, comme je l'ai découvert au cours de plusieurs heures de recherche. Mais je n'ai pas encore trouvé d'exemples, ni d'explications claires sur la façon de procéder, même si beaucoup disent que c'est possible avec le plugin jQuery. Quelqu'un peut-il citer des exemples? Je n'ai aucune idée de comment même commencer. Merci beaucoup.

<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://cdn.datatables.net/1.10.16/js/jquery.dataTables.min.js"></script>
<script src="https://cdn.datatables.net/1.10.16/css/jquery.dataTables.min.css"></script>

    $(document).ready(function() {
    $('#example').DataTable( {
        initComplete: function () {
            this.api().columns().every( function () {
                var column = this;
                var select = $('<select multiple="multiple"><option value=""></option></select>')
                    .appendTo( $(column.footer()).empty() )
                    .on( 'change', function () {
                        var vals = $('option:selected', this).map(function (index, element) {
                            return $.fn.dataTable.util.escapeRegex($(element).val());
                        }).toArray().join('|');

                        column
                            .search( vals.length > 0 ? '^('+vals+')$' : '', true, false )
                            .draw();
                    } );

                column.data().unique().sort().each( function ( d, j ) {
                    select.append( '<option value="'+d+'">'+d+'</option>' )
                } );
            } );
        }
    } );
} );
5
Silverburch

Essayez ceci, qui n’utilise aucune bibliothèque JS/jQuery supplémentaire:

// This code has been beautified via http://jsbeautifier.org/ with 2 spaces indentation.
$(document).ready(function() {
  function cbDropdown(column) {
    return $('<ul>', {
      'class': 'cb-dropdown'
    }).appendTo($('<div>', {
      'class': 'cb-dropdown-wrap'
    }).appendTo(column));
  }

  $('#example').DataTable({
    initComplete: function() {
      this.api().columns().every(function() {
        var column = this;
        var ddmenu = cbDropdown($(column.header()))
          .on('change', ':checkbox', function() {
            var active;
            var vals = $(':checked', ddmenu).map(function(index, element) {
              active = true;
              return $.fn.dataTable.util.escapeRegex($(element).val());
            }).toArray().join('|');

            column
              .search(vals.length > 0 ? '^(' + vals + ')$' : '', true, false)
              .draw();

            // Highlight the current item if selected.
            if (this.checked) {
              $(this).closest('li').addClass('active');
            } else {
              $(this).closest('li').removeClass('active');
            }

            // Highlight the current filter if selected.
            var active2 = ddmenu.parent().is('.active');
            if (active && !active2) {
              ddmenu.parent().addClass('active');
            } else if (!active && active2) {
              ddmenu.parent().removeClass('active');
            }
          });

        column.data().unique().sort().each(function(d, j) {
          var // wrapped
            $label = $('<label>'),
            $text = $('<span>', {
              text: d
            }),
            $cb = $('<input>', {
              type: 'checkbox',
              value: d
            });

          $text.appendTo($label);
          $cb.appendTo($label);

          ddmenu.append($('<li>').append($label));
        });
      });
    }
  });
});

CSS

/* Styles for the drop-down. Feel free to change the styles to suit your website. :-) */

.cb-dropdown-wrap {
  max-height: 80px; /* At most, around 3/4 visible items. */
  position: relative;
  height: 19px;
}

.cb-dropdown,
.cb-dropdown li {
  margin: 0;
  padding: 0;
  list-style: none;
}

.cb-dropdown {
  position: absolute;
  z-index: 1;
  width: 100%;
  height: 100%;
  overflow: hidden;
  background: #fff;
  border: 1px solid #888;
}

/* For selected filter. */
.active .cb-dropdown {
  background: pink;
}

.cb-dropdown-wrap:hover .cb-dropdown {
  height: 80px;
  overflow: auto;
  transition: 0.2s height ease-in-out;
}

/* For selected items. */
.cb-dropdown li.active {
  background: #ff0;
}

.cb-dropdown li label {
  display: block;
  position: relative;
  cursor: pointer;
  line-height: 19px; /* Match height of .cb-dropdown-wrap */
}

.cb-dropdown li label > input {
  position: absolute;
  right: 0;
  top: 0;
  width: 16px;
}

.cb-dropdown li label > span {
  display: block;
  margin-left: 3px;
  margin-right: 20px; /* At least, width of the checkbox. */
  font-family: sans-serif;
  font-size: 0.8em;
  font-weight: normal;
  text-align: left;
}

/* This fixes the vertical aligning of the sorting icon. */
table.dataTable thead .sorting,
table.dataTable thead .sorting_asc,
table.dataTable thead .sorting_desc,
table.dataTable thead .sorting_asc_disabled,
table.dataTable thead .sorting_desc_disabled {
  background-position: 100% 10px;
}

Démo

https://jsfiddle.net/41vgefnf/1/
https://jsfiddle.net/41vgefnf/6/
https://jsfiddle.net/41vgefnf/8/
https://jsfiddle.net/41vgefnf/9/
https://jsfiddle.net/41vgefnf/10/

METTRE &AGRAVE; JOUR

J'ai déplacé les listes déroulantes de filtres dans l'en-tête et les ai stylisées pour ressembler davantage à des menus déroulants. (Aucun JS ou jQuery n’est impliqué dans la fonctionnalité de liste déroulante}; juste du CSS pur avec une animation de base - CSS3 transition.)

UPDATE # 2

Désolé, j'ai oublié d'appliquer le CSS "actif" class aux éléments sélectionnés.

UPDATE # 3

Identique à Mise à jour 2 cas, mais pour le wrapper du menu déroulant. (Désolé de continuer à oublier des choses .. et j'ai édité juste pour se conformer/répondre aux exigences/changements que vous avez réellement demandés. :) Mais je pense que cette mise à jour serait la dernière révision.)

UPDATE # 4

Correction du "actif" changement d'état du wrapper du menu déroulant.

CR&EACUTE;DITS

Merci @Giacomo pour votre Fiddle . =)

7
Sally CJ

Je pense que ce que vous recherchez en termes d'interface utilisateur est un multisélection.

Il n’existe pas réellement d’élément de liste déroulante avec sélection multiple utilisant une case à cocher (multiselect existe déjà pour ce type de besoin d’interaction).

Je pense que vous avez besoin d’un multisélection personnalisé offrant une meilleure expérience utilisateur (pas celui par défaut comme dans l’exemple fourni).

Je comprends que ce n’est pas exactement ce que vous demandiez, mais je pense que cela répondra à votre demande à un niveau plus abstrait.

Tout ce que j'ai fait est d'utiliser un plugin jquery appelé select2, très utile pour améliorer ux et ui dans divers éléments d'entrée.

S'il vous plaît vérifier les commentaires de code pour les détails techniques.

https://jsfiddle.net/p1261jby/3/

/*added as resources
https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/js/select2.min.js
https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/css/select2.min.css
*/

$(document).ready(function() {
  $('#example').DataTable({
    initComplete: function() {
      this.api().columns().every(function() {
        var column = this;
        //added class "mymsel"
        var select = $('<select class="mymsel" multiple="multiple"><option value=""></option></select>')
          .appendTo($(column.footer()).empty())
          .on('change', function() {
            var vals = $('option:selected', this).map(function(index, element) {
              return $.fn.dataTable.util.escapeRegex($(element).val());
            }).toArray().join('|');

            column
              .search(vals.length > 0 ? '^(' + vals + ')$' : '', true, false)
              .draw();
          });

        column.data().unique().sort().each(function(d, j) {
          select.append('<option value="' + d + '">' + d + '</option>')
        });
      });
      //select2 init for .mymsel class
      $(".mymsel").select2();
    }
  });
});

Voici les documents Select2 au cas où vous auriez besoin de personnaliser certains paramètres . https://select2.org/selections

4
Giacomo Penuti

Voici une autre saveur. Il utilise un code modifié à partir de Elmahdi Mahmoud pour la sélection multiple. Je laisse donc son message de copyright MIT.

Je vous préviens maintenant, le code n'est pas joli, mais le résultat est efficace, alors j'ai pensé qu'il valait la peine d'ajouter à la pile d'options. Un violon live est ici .

Le JS est

    /* Plugin API method to determine is a column is sortable */
$.fn.dataTable.Api.register('column().searchable()', function() {
  var ctx = this.context[0];
  return ctx.aoColumns[this[0]].bSearchable;
});


$(document).ready(function() {
  // Create the DataTable
  var table = $('#example').DataTable({
    fixedHeader: true,
    pageLength: 25,
    orderCellsTop: true,
    columnDefs: [{
      searchable: false,
      targets: [0, 4]
    }],
  });

  // Add filtering
  table.columns().every(function() {
    if (this.searchable()) {
      var that = this;


      var myList = $('<ul/>');
      var myMulti = $('<div class="mutliSelect"/>');
      myList.appendTo(myMulti);

      var myDd = $('<dd/>');
      myMulti.appendTo(myDd);

      var myDropdown = $('<dl class="dropdown"/>');
      myDropdown.append('<dt><a href="#"><span class="hida">Select</span><p class="multiSel"></p></a></dt>');
      myDd.appendTo(myDropdown);

      myDropdown
        .appendTo(
          $('thead tr:eq(1) td').eq(this.index())
        )
        .on('change', function() {
          var vals = $(':checked', this).map(function(index, element) {
            return $.fn.dataTable.util.escapeRegex($(element).val());
          }).toArray().join('|');

          that
            .search(vals.length > 0 ? '^(' + vals + ')$' : '', true, false)
            .draw();
        });


      // Add data
      this
        .data()
        .sort()
        .unique()
        .each(function(d) {
          myList.append($('<li><input type="checkbox" value="' + d + '"/>' + d + '</option>'));
        });

    }
  });


  /*
    Dropdown with Multiple checkbox select with jQuery - May 27, 2013
    (c) 2013 @ElmahdiMahmoud
    license: https://www.opensource.org/licenses/mit-license.php
  */

  $(".dropdown dt a").on('click', function(e) {
    var dropdown = $(this).closest('.dropdown');
    dropdown.find('ul').slideToggle('fast');

    $('.dropdown').not(dropdown).find('ul').slideUp('fast');

  });

  $(".dropdown dd ul li a").on('click', function() {
    $(".dropdown dd ul").hide();
  });

  function getSelectedValue(id) {
    return $("#" + id).find("dt a span.value").html();
  }

  $(document).bind('click', function(e) {
    var $clicked = $(e.target);
    if (!$clicked.parents().hasClass("dropdown")) $(".dropdown dd ul").slideUp('fast');

  });

  $('.multiSelect input[type="checkbox"]').on('click', function() {
    var title = $(this).closest('.multiSelect').find('input[type="checkbox"]').val(),
      title = $(this).val() + ",";

    if ($(this).is(':checked')) {
      var html = '<span title="' + title + '">' + title + '</span>';
      $('.multiSel').append(html);
      $(".hida").hide();
    } else {
      $('span[title="' + title + '"]').remove();
      var ret = $(".hida");
      $('.dropdown dt a').append(ret);

    }
  });


});
2
colin0117