El menú desplegable del botón Bootstrap dentro de la tabla receptiva no es visible debido al desplazamiento

86

Tengo un problema con los botones desplegables dentro de las tablas cuando responden y se desplazan activos porque el menú desplegable no es visible debido a overflow: auto; propiedad. ¿Cómo puedo solucionarlo para mostrar la opción desplegable del botón cuando está contraído? Puedo usar jQuery, pero después de tener problemas con el desplazamiento de izquierda a derecha, decidí buscar otra solución. Adjunto una foto para entender mejor.ingrese la descripción de la imagen aquí

Aquí hay un pequeño violín js:

BurebistaRuler
fuente

Respuestas:

60

Lo resolví yo mismo y puse la respuesta en el alcance para ayudar a otros usuarios que tienen el mismo problema: tenemos un evento en bootstrap y podemos usar ese evento para configurar, overflow: inheritpero esto funcionará si no tiene la propiedad css en su padre envase.

$('.table-responsive').on('show.bs.dropdown', function () {
     $('.table-responsive').css( "overflow", "inherit" );
});

$('.table-responsive').on('hide.bs.dropdown', function () {
     $('.table-responsive').css( "overflow", "auto" );
})

y este es el violín

info: En este violín, el ejemplo funciona de forma extraña y no estoy seguro de por qué, pero en mi proyecto funciona bien.

BurebistaRuler
fuente
3
Esto solo funciona para tablas con un menú desplegable en la primera celda de la línea.
Almino Melo
6
en caso de tabla cargada dinámica: $('body') .on('show.bs.dropdown', '.table-responsive', function () { $(this).css("overflow", "visible"); }) .on('hide.bs.dropdown', '.table-responsive', function () { $(this).css("overflow", "auto"); });
Exlord
4
Pero después del clic, los datos salen del tamaño mínimo de la pantalla. Entonces esto no funciona. !!!!
Shreya Shah
1
Esto funcionaría si pudiera evitar que la tabla se desplace hacia la izquierda cuando se abre el menú desplegable. Pero tal como está, si tiene un menú desplegable a la derecha de la pantalla, la mesa se mueve hacia la izquierda al abrirse. Los menús desplegables que están más a la derecha (enmascarados por la .table-responsiveclase) están completamente ocultos cuando se intenta editarlos.
Ponyboy
43

Una única solución de CSS es permitir que el eje y se desborde.

http://www.bootply.com/YvePJTDzI0

.table-responsive {
  overflow-y: visible !important;
}

EDITAR

Otra única solución de CSS es aplicar el desbordamiento de manera receptiva según el ancho de la ventana gráfica:

@media (max-width: 767px) {
    .table-responsive .dropdown-menu {
        position: static !important;
    }
}
@media (min-width: 768px) {
    .table-responsive {
        overflow: inherit;
    }
}

https://www.codeply.com/go/D3XBvspns4

Zim
fuente
@ZimSystem Todavía hace lo mismo, fundamentalmente, esta no es la solución.
Jemar Jones
Esta solución funciona incluso si elimina el css personalizado. Tal vez sea una cuestión de HTML. Todavía estoy buscando una solución solo de CSS.
fernandodof
1
No. No funciona. Supongo que es porque estoy usando tablas de datos
peterchaula
funciona para mí, excepto que el botón está en la parte inferior de la página ... luego el menú desplegable aparece fuera de la ventana ...
Brucie Alpha
31

Como referencia, es 2018 y estoy usando BS4.1

Intente agregar data-boundary="viewport"al botón que alterna el menú desplegable (el que tiene la clase dropdown-toggle). Ver https://getbootstrap.com/docs/4.1/components/dropdowns/#options

Ben
fuente
4
Confirmo que esta es una solución funcional que se me ocurrió también.
sdvnksv
4
No puedo hablar de versiones anteriores, pero para Bootstrap 4 esta es realmente la mejor solución. Es simple, no sacrifica la capacidad de respuesta, utiliza la funcionalidad que ya se proporciona en el marco en lugar de intentar piratearlo con estilos o scripts adicionales.
T. Linnell
16

Tomé un enfoque diferente, separé el elemento del padre y lo configuré con la posición absoluta de jQuery

Trabajo JS violín: http://jsfiddle.net/s270Lyrd/

ingrese la descripción de la imagen aquí

La solución JS que estoy usando.

//fix menu overflow under the responsive table 
// hide menu on click... (This is a must because when we open a menu )
$(document).click(function (event) {
    //hide all our dropdowns
    $('.dropdown-menu[data-parent]').hide();

});
$(document).on('click', '.table-responsive [data-toggle="dropdown"]', function () {
    // if the button is inside a modal
    if ($('body').hasClass('modal-open')) {
        throw new Error("This solution is not working inside a responsive table inside a modal, you need to find out a way to calculate the modal Z-index and add it to the element")
        return true;
    }

    $buttonGroup = $(this).parent();
    if (!$buttonGroup.attr('data-attachedUl')) {
        var ts = +new Date;
        $ul = $(this).siblings('ul');
        $ul.attr('data-parent', ts);
        $buttonGroup.attr('data-attachedUl', ts);
        $(window).resize(function () {
            $ul.css('display', 'none').data('top');
        });
    } else {
        $ul = $('[data-parent=' + $buttonGroup.attr('data-attachedUl') + ']');
    }
    if (!$buttonGroup.hasClass('open')) {
        $ul.css('display', 'none');
        return;
    }
    dropDownFixPosition($(this).parent(), $ul);
    function dropDownFixPosition(button, dropdown) {
        var dropDownTop = button.offset().top + button.outerHeight();
        dropdown.css('top', dropDownTop + "px");
        dropdown.css('left', button.offset().left + "px");
        dropdown.css('position', "absolute");

        dropdown.css('width', dropdown.width());
        dropdown.css('heigt', dropdown.height());
        dropdown.css('display', 'block');
        dropdown.appendTo('body');
    }
});
Wazime
fuente
1
Esta respuesta es la solución perfecta para mí mientras uso jquery datatable (renderizado ajax). Me ajusté en consecuencia y funciona muy bien.
13

Esta solución funcionó muy bien para mí:

@media (max-width: 767px) {
    .table-responsive .dropdown-menu {
        position: static !important;
    }
}
@media (min-width: 768px) {
    .table-responsive {
        overflow: visible;
    }
}

Más detalles: https://github.com/twbs/bootstrap/issues/15374

pham cuong
fuente
11

mi solución global rápida de 2 ¢:

// drop down in responsive table

(function () {
  $('.table-responsive').on('shown.bs.dropdown', function (e) {
    var $table = $(this),
        $menu = $(e.target).find('.dropdown-menu'),
        tableOffsetHeight = $table.offset().top + $table.height(),
        menuOffsetHeight = $menu.offset().top + $menu.outerHeight(true);

    if (menuOffsetHeight > tableOffsetHeight)
      $table.css("padding-bottom", menuOffsetHeight - tableOffsetHeight);
  });

  $('.table-responsive').on('hide.bs.dropdown', function () {
    $(this).css("padding-bottom", 0);
  })
})();

Explicaciones: cuando se muestra un menú desplegable dentro de un '.table-responsive', calcula la altura de la tabla y la expande (con relleno) para que coincida con la altura requerida para mostrar el menú. El menú puede ser de cualquier tamaño.

En mi caso, esta no es la tabla que tiene la clase '.table-responsive', es un div envolvente:

<div class="table-responsive" style="overflow:auto;">
    <table class="table table-hover table-bordered table-condensed server-sort">

¡Así que $ table var en el script es en realidad un div! (solo para que quede claro ... o no) :)

Nota: lo envuelvo en una función para que mi IDE pueda colapsar la función;) ¡pero no es obligatorio!

BaltazarQc
fuente
2
Esta es la única solución que funcionó para mí, pero sugeriría usar $ table.css ("padding-bottom", menuOffsetHeight - tableOffsetHeight + 16); inserción de $ table.css ("padding-bottom", menuOffsetHeight - tableOffsetHeight); para agregar relleno adicional que está en bootstrap por defecto, más un pequeño espacio en la parte inferior.
Phil Young
Esto funciona, pero el acolchado hace que se vea mal. Ojalá hubiera una solución que lo hiciera funcionar sin la hinchazón del relleno.
Qasim
solución agradable y simple
NMC
11

Tengo una solución que usa solo CSS, solo use la posición relativa para los menús desplegables dentro de la tabla:

@media (max-width: 767px) {
  .table-responsive .dropdown-menu {
    position: relative; /* Sometimes needs !important */
  }
}

https://codepen.io/leocaseiro/full/rKxmpz/

Leo Caseiro
fuente
1
esta es la mejor solución, la estoy usando para ui-select en mi tabla receptiva.
Sergio Ivanuzzo
La mejor solución también para mí
Mauro
2
Este violín no funciona . Se mantiene escondido en el menú desplegable debajo de la mesa.
HelloIT
@HelloIT prueba el codepen (actualizado) codepen.io/leocaseiro/pen/rKxmpz
Leo Caseiro
1
De acuerdo con @hellioIT, este método no parece estar funcionando en la pluma
MrPaulDriver
9

Defina estas propiedades. ¡Buena suerte!

data-toggle="dropdown" data-boundary="window"
Halit Yeşil
fuente
3
Bootstrap 4 única solución
nevada_scout
5

Esto se ha solucionado en Bootstrap v4.1 y superior agregando data-boundary="viewport"( Bootstrap Dropdowns Docs )

Pero para versiones anteriores (v4.0 y anteriores), encontré este fragmento de JavaScript que funciona perfectamente. Funciona para mesas pequeñas y mesas de desplazamiento:

$('.table-responsive').on('shown.bs.dropdown', function (e) {
    var t = $(this),
        m = $(e.target).find('.dropdown-menu'),
        tb = t.offset().top + t.height(),
        mb = m.offset().top + m.outerHeight(true),
        d = 20; // Space for shadow + scrollbar.
    if (t[0].scrollWidth > t.innerWidth()) {
        if (mb + d > tb) {
            t.css('padding-bottom', ((mb + d) - tb));
        }
    }
    else {
        t.css('overflow', 'visible');
    }
}).on('hidden.bs.dropdown', function () {
    $(this).css({'padding-bottom': '', 'overflow': ''});
});
Cyrus V.
fuente
4

Se limpió un poco la solución @Wazime. Funciona muy bien como solución general.

$(document).on('shown.bs.dropdown', '.table-responsive', function (e) {
    // The .dropdown container
    var $container = $(e.target);

    // Find the actual .dropdown-menu
    var $dropdown = $container.find('.dropdown-menu');
    if ($dropdown.length) {
        // Save a reference to it, so we can find it after we've attached it to the body
        $container.data('dropdown-menu', $dropdown);
    } else {
        $dropdown = $container.data('dropdown-menu');
    }

    $dropdown.css('top', ($container.offset().top + $container.outerHeight()) + 'px');
    $dropdown.css('left', $container.offset().left + 'px');
    $dropdown.css('position', 'absolute');
    $dropdown.css('display', 'block');
    $dropdown.appendTo('body');
});

$(document).on('hide.bs.dropdown', '.table-responsive', function (e) {
    // Hide the dropdown menu bound to this button
    $(e.target).data('dropdown-menu').css('display', 'none');
});
temblores
fuente
2

La solución recomendada y elegida, no siempre es la mejor solución. Desafortunadamente, es la solución que linkedin usó recientemente y crea múltiples barras de desplazamiento en la página según la situación.

Mi método fue ligeramente diferente.

Contuve el div que responde a la tabla en otro div. Luego apliqué altura 100%, ancho: 100%, bloque de visualización y posición absoluta para que la altura y el ancho se basen en el tamaño de la página, y establecí el desbordamiento en oculto.

Luego, en el div receptivo de la mesa, agregué una altura mínima del 100%

<div class="table_container" 
    style="height: 100%; width: 100%; display: block;position: absolute;overflow: hidden;">
<div class="table-responsive" style="min-height:100%;">

Como puede ver en el ejemplo de trabajo a continuación, sin barras de desplazamiento agregadas, sin comportamiento divertido y prácticamente como usa porcentajes, debería funcionar independientemente del tamaño de la pantalla. Sin embargo, no he probado esto para eso. Si eso falla por alguna razón, se puede reemplazar el 100% con 100vh y 100vw respectivamente.

<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">

<!-- Optional theme -->
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">

            <script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>


<div class="table_container" style="height: 100%; width: 100%; display: block;position: absolute;overflow: hidden;">
<div class="table-responsive" style="min-height:100%;">
                <table class="table">
                    <thead>
                        <tr>
                            <th>Value1</th>
                            <th>Value2</th>
                            <th>Value3</th>
                            <th>Value4</th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr>
                            <td>
                                DATA
                                <div class="btn-group btn-group-rounded">
                                    <button type="button" class="btn btn-default btn-xs" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" style="border-radius:3px;">
                                        <span class="caret"></span>
                                    </button>
                                    <ul class="dropdown-menu">
                                        <li><a href="#">One</a></li>
                                        <li><a href="#">Two</a></li>
                                        <li><a href="#">Three</a></li>
                                        <li role="seperator" class="divider"></li>
                                        <li><a href="#">Four</a></li>
                                    </ul>
                                </div>
                            </td>

                            <td>
                                DATA
                                <div class="btn-group btn-group-rounded">
                                    <button type="button" class="btn btn-default btn-xs" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" style="border-radius:3px;">
                                        <span class="caret"></span>
                                    </button>
                                    <ul class="dropdown-menu">
                                        <li><a href="#">One</a></li>
                                        <li><a href="#">Two</a></li>
                                        <li><a href="#">Three</a></li>
                                        <li role="seperator" class="divider"></li>
                                        <li><a href="#">Four</a></li>
                                    </ul>
                                </div>
                            </td>
                            <td>
                                DATA
                                <div class="btn-group btn-group-rounded">
                                    <button type="button" class="btn btn-default btn-xs" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" style="border-radius:3px;">
                                        <span class="caret"></span>
                                    </button>
                                    <ul class="dropdown-menu">
                                        <li><a href="#">One</a></li>
                                        <li><a href="#">Two</a></li>
                                        <li><a href="#">Three</a></li>
                                        <li role="seperator" class="divider"></li>
                                        <li><a href="#">Four</a></li>
                                    </ul>
                                </div>
                            </td>
                            <td>DATA</td>
                        </tr>
                        <tr>
                            <td>
                                DATA
                                <div class="btn-group btn-group-rounded">
                                    <button type="button" class="btn btn-default btn-xs" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" style="border-radius:3px;">
                                        <span class="caret"></span>
                                    </button>
                                    <ul class="dropdown-menu">
                                        <li><a href="#">One</a></li>
                                        <li><a href="#">Two</a></li>
                                        <li><a href="#">Three</a></li>
                                        <li role="seperator" class="divider"></li>
                                        <li><a href="#">Four</a></li>                                    </ul>
                                </div>
                            </td>

                            <td>
                                DATA
                                <div class="btn-group btn-group-rounded">
                                    <button type="button" class="btn btn-default btn-xs" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" style="border-radius:3px;">
                                        <span class="caret"></span>
                                    </button>
                                    <ul class="dropdown-menu">
                                        <li><a href="#">One</a></li>
                                        <li><a href="#">Two</a></li>
                                        <li><a href="#">Three</a></li>
                                        <li role="seperator" class="divider"></li>
                                        <li><a href="#">Four</a></li>
                                    </ul>
                                </div>
                            </td>
                            <td>
                                DATA
                                <div class="btn-group btn-group-rounded">
                                    <button type="button" class="btn btn-default btn-xs" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" style="border-radius:3px;">
                                        <span class="caret"></span>
                                    </button>
                                    <ul class="dropdown-menu">
                                        <li><a href="#">One</a></li>
                                        <li><a href="#">Two</a></li>
                                        <li><a href="#">Three</a></li>
                                        <li role="seperator" class="divider"></li>
                                        <li><a href="#">Four</a></li>
                                    </ul>
                                </div>
                            </td>
                            <td>DATA</td>
                        </tr>
                    </tbody>
                </table>
            </div>
</div>

Bruce
fuente
No es una solución para alturas de vista más pequeñas. Ya no se puede acceder a los enlaces desplegables inferiores debido a que están fuera de la vista.
Seika85
1

Según la respuesta aceptada y la respuesta de @LeoCaseiro, esto es lo que terminé usando en mi caso:

@media (max-width: 767px) {
    .table-responsive{
        overflow-x: auto;
        overflow-y: auto;
    }
}
@media (min-width: 767px) {
    .table-responsive{
        overflow: inherit !important; /* Sometimes needs !important */
    }
}

en las pantallas grandes, el menú desplegable no estará oculto detrás de la tabla de respuestas y en la pantalla pequeña estará oculto, pero está bien porque de todos modos hay una barra de desplazamiento en el móvil.

Espero que esto ayude a alguien.

medBouzid
fuente
0

La respuesta de Burebistaruler funciona bien para mí en ios8 (iphone4s) pero no funciona en Android que antes funcionaba. Lo que he hecho que funciona para mí en ios8 (iphone4s) y andoir es:

$('.table-responsive').on('show.bs.dropdown', function () {
 $('.table-responsive').css( "min-height", "400px" );
});

$('.table-responsive').on('hide.bs.dropdown', function () {
     $('.table-responsive').css( "min-height", "none" );
})
Oscar Jofre
fuente
0

Esto podría ser útil para otra persona. Estoy usando DatatablesJS. Agrego 500px a la altura actual de la mesa. Hago esto porque las tablas de datos le permiten usar 10, 20, etc. páginas en su tabla. Entonces necesito calcular dinámicamente la altura de la mesa.
Cuando se muestra el menú desplegable, agrego altura adicional.
Cuando el menú desplegable está oculto, restablezco la altura de la tabla original.

$(document).ready(function() {
    $('.table-responsive .dropdown').on('shown.bs.dropdown', function () {
          console.log($('#table-responsive-cliente').height() + 500)
          $("#table-responsive-cliente").css("height",$('#table-responsive-cliente').height() + 500 );
    })

    $('.table-responsive .dropdown').on('hide.bs.dropdown', function () {
           $("#table-responsive-cliente").css("height","auto");
    })
})

Y el HTML

<div class="table-responsive" id="table-responsive-cliente">
    <table class="table-striped table-hover">
     ....

     ....
    </table>
</div>

Antes de: ingrese la descripción de la imagen aquí

Después de que se muestre el menú desplegable: ingrese la descripción de la imagen aquí

Miguel Angel
fuente
0

Resolvimos este problema aquí en el trabajo aplicando una clase .dropup al menú desplegable cuando el menú desplegable está cerca de la parte inferior de una tabla. ingrese la descripción de la imagen aquí

roshin jose
fuente
Estoy muy feliz con esa solución al final. $('table tr:nth-last-child(-n+3) td').addClass('dropup').
Furgas
0

Esto funcionó para mí en Bootstrap 4 ya que tiene diferentes puntos de interrupción que v3:

@media (min-width: 992px) {
    .table-responsive {
        overflow: inherit;
    }
}
ar31an
fuente
0

Siempre y cuando la gente siga estancada en este problema y ya estemos en 2020. Obtengo una solución CSS pura al darle al menú desplegable una pantalla flexible

este fragmento funciona muy bien con la datatable-scroll-wrapclase

.datatable-scroll-wrap .dropdown.dropup.open .dropdown-menu {
    display: flex;
}
.datatable-scroll-wrap .dropdown.dropup.open .dropdown-menu li a {
    display: flex;
}
hassan
fuente
0

Bueno, al leer la respuesta principal, vi que realmente no funciona cuando ves la barra de desplazamiento y el botón de alternar estaba en la última columna (en mi caso) u otra columna que no se ve

error de imagen

Pero, si cambia 'heredar' por 'oculto', funcionará.

$('.table-responsive').on('show.bs.dropdown', function () {
    $('.table-responsive').css( "overflow", "hidden" );
}).on('hide.bs.dropdown', function () {
    $('.table-responsive').css( "overflow", "auto" );
})

ingrese la descripción de la imagen aquí

Intenta hacerlo de esa manera.

Luís Gustavo Batista
fuente
-1

Dentro de bootstrap.css busque el siguiente código:

.fixed-table-body {
  overflow-x: auto;
  overflow-y: auto;
  height: 100%;
}

... y actualiza con esto:

.fixed-table-body {
  overflow-x: visible;
  overflow-y: visible;
  height: 100%;
}
Cesar
fuente
-1

Simplemente use esto

.table-responsive {
    overflow: inherit;
}

Funciona en Chrome, pero no en IE10 o Edge porque la propiedad heredada no es compatible

Deepak Swain
fuente
-1

En mi caso, esto funciona bien:

.table-responsive {
  overflow-y: visible !important;
}
Hamid
fuente