¿Controladores de eventos para los menús desplegables de Twitter Bootstrap?

86

Me gustaría usar un botón desplegable de Twitter Bootstrap :

    <div class="btn-group">
      <button class="btn dropdown-toggle" data-toggle="dropdown">Action <span class="caret"></span></button>
      <ul class="dropdown-menu">
        <li><a href="#">Action</a></li>
        <li><a href="#">Another action</a></li>
        <li><a href="#">Something else here</a></li>
      </ul>
    </div><!-- /btn-group -->

Cuando el usuario cambia el valor del botón a 'Otra acción', en lugar de simplemente navegar #, me gustaría manejar la acción de una manera personalizada.

Pero no puedo ver ningún controlador de eventos en el complemento desplegable para hacer esto.

¿Es realmente posible usar los botones desplegables de Bootstrap para manejar las acciones del usuario? Empiezo a preguntarme si solo están destinados a la navegación; es confuso que el ejemplo proporcione una lista de acciones.

Ricardo
fuente
1
¿No funcionaría una función que se activa al hacer clic en la etiqueta de anclaje?
Cameron Chapman
El primero de estos no son botones, son anclas. Puede echar un vistazo a los controladores de eventos inspeccionando el archivo bootstrap.js. Pero hasta donde yo sé, todas estas acciones se procesan con jQuery, por lo que no debería ser un gran problema editar o anular esta funcionalidad.
mas-designs

Respuestas:

78

Twitter bootstrap está destinado a brindar una funcionalidad básica y solo proporciona complementos básicos de JavaScript que hacen algo en la pantalla . Cualquier contenido o funcionalidad adicional, deberá hacerlo usted mismo.

<div class="btn-group">
  <button class="btn dropdown-toggle" data-toggle="dropdown">Action <span class="caret"></span></button>
  <ul class="dropdown-menu">
    <li><a href="#" id="action-1">Action</a></li>
    <li><a href="#" id="action-2">Another action</a></li>
    <li><a href="#" id="action-3">Something else here</a></li>
  </ul>
</div><!-- /btn-group -->

y luego con jQuery

jQuery("#action-1").click(function(e){
//do something
e.preventDefault();
});
Thomas Jones
fuente
1
Lo intenté, sin embargo, sin que se disparara ningún evento. Sin embargo, puedo captar el evento de hacer clic en un botón. ¿Qué más podría estar en el camino?
Llave inglesa
1
@RonnieKilsbo no estoy seguro. Esta solución funciona como se indicó y la he usado innumerables veces. Es posible que no esté configurando la identificación de su ancla correctamente, o puede que esté vinculando antes de que existan los elementos; recomiendo usar jQuery en este caso.
Thomas Jones
1
Tienes razón, mi culpa. Había insertado elementos en el DOM después de vincular los clics con jQuery, lo cual es malo. :) Trabajando, confirmado.
Llave inglesa
18

Prueba esto:

$('div.btn-group ul.dropdown-menu li a').click(function (e) {
    var $div = $(this).parent().parent().parent(); 
    var $btn = $div.find('button');
    $btn.html($(this).text() + ' <span class="caret"></span>');
    $div.removeClass('open');
    e.preventDefault();
    return false;
});
Fernando
fuente
14

En Bootstrap 3, 'dropdown.js' nos proporciona los diversos eventos que se activan.

click.bs.dropdown
show.bs.dropdown
shown.bs.dropdown

etc

Stevanicus
fuente
Eso es cierto, pero todavía no trabaja dentro del marco de arranque para adjuntar controladores de eventos. Haces eso por tu cuenta. Bootstrap siempre se ha tratado de hacer cosas en la pantalla, no de proporcionar una funcionalidad personalizada. Se supone que el desarrollador podrá conectar sus propios eventos desplegables.
Thomas Jones
8

Aquí hay un ejemplo práctico de cómo podría implementar funciones personalizadas para sus anclajes.

http://jsfiddle.net/CH2NZ/43/

Puede adjuntar una identificación a su ancla:

<li><a id="alertMe" href="#">Action</a></li>

Y luego use el detector de eventos de clic de jQuery para escuchar la acción de clic y activar su función:

$('#alertMe').click(function(e) {
    alert('alerted');
    e.preventDefault();// prevent the default anchor functionality
});
Cameron Chapman
fuente
El ejemplo anterior ya no parece existir en jsfiddle.
Ethereal
Agregué un nuevo ejemplo con un enlace válido. Gracias @ethereal.
Cameron Chapman
4

He estado mirando esto. Al completar los anclajes desplegables, les he dado una clase y atributos de datos, por lo que cuando necesite realizar una acción, puede hacer:

<li><a class="dropDownListItem" data-name="Fred Smith" href="#">Fred</a></li>

y luego en jQuery haciendo algo como:

$('.dropDownListItem').click(function(e) {
    var name = e.currentTarget;
    console.log(name.getAttribute("data-name"));
});

Entonces, si ha generado dinámicamente elementos de lista en su menú desplegable y necesita usar los datos que no son solo el valor de texto del elemento, puede usar los atributos de datos al crear el elemento de lista desplegable y luego simplemente dar a cada elemento con la clase el evento, en lugar de hacer referencia a los ID de cada elemento y generar un evento de clic.

Andrew Berry
fuente
3

Cualquiera que busque la integración de Knockout JS.

Dado el siguiente HTML (botón desplegable de Bootstrap estándar):

<div class="dropdown">
    <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">
        Select an item               
        <span class="caret"></span>
    </button>
    <ul class="dropdown-menu" role="menu">
        <li>
            <a href="javascript:;" data-bind="click: clickTest">Click 1</a>
        </li>
        <li>
            <a href="javascript:;" data-bind="click: clickTest">Click 2</a>
        </li>
        <li>
            <a href="javascript:;" data-bind="click: clickTest">Click 3</a>
        </li>
    </ul>
</div>

Utilice el siguiente JS:

var viewModel = function(){
    var self = this;

    self.clickTest = function(){
        alert("I've been clicked!");
    }  
};

Para aquellos que buscan generar opciones desplegables basadas en una matriz observable knockout, el código se vería así:

var viewModel = function(){
    var self = this;

    self.dropdownOptions = ko.observableArray([
        { id: 1, label: "Click 1" },
        { id: 2, label: "Click 2" },
        { id: 3, label: "Click 3" }
    ])

    self.clickTest = function(item){
        alert("Item with id:" + item.id + " was clicked!");
    }  
};

<!-- REST OF DD CODE -->
<ul class="dropdown-menu" role="menu">
    <!-- ko foreach: { data: dropdownOptions, as: 'option' } -->
    <li>
        <a href="javascript:;" data-bind="click: $parent.clickTest, text: option.clickTest"></a>
    </li>
    <!-- /ko -->
</ul>
<!-- REST OF DD CODE -->

Tenga en cuenta que el elemento de matriz observable se pasa implícitamente al controlador de la función de clic para su uso en el código del modelo de vista.

pim
fuente
3

Sin tener que cambiar el grupo de botones en absoluto, puede hacer lo siguiente. A continuación, supongo que su desplegable buttontiene una idde fldCategory.

<script type="text/javascript">

$(document).ready(function(){

  $('#fldCategory').parent().find('UL LI A').click(function (e) {
    var sVal = e.currentTarget.text;
    $('#fldCategory').html(sVal + ' <span class="caret"></span>');
    console.log(sVal);
  });

});

</script>

Ahora, si configura el .btn-groupde este elemento para tener el idde fldCategory, eso es en realidad jQuery más eficiente y se ejecuta un poco más rápido:

<script type="text/javascript">

$(document).ready(function(){

  $('#fldCategory UL LI A').click(function (e) {
    var sVal = e.currentTarget.text;
    $('#fldCategory BUTTON').html(sVal + ' <span class="caret"></span>');
    console.log(sVal);
  });

});

</script>
Volomike
fuente
¡Decir ah! ¡Gracias eso es astuto! :) Usé tu segundo ejemplo.
drzounds
esta debería haber sido la respuesta!
Jake