2012-09-13 8 views
17

estoy usando el componente Typeahead de Twitter Bootstrap 2.1.1, 1.8.1 y jQueryTwitter Bootstrap de escritura siguiente: llegar contexto/elemento con `llamando this`

Estoy tratando de acceder al elemento de cuadro de texto desde dentro de TYPEAHEAD updater función. Aquí está mi código actual, que funciona muy bien:

$('#client-search').typeahead({ 
    source: function (query, process) { 
     $.get(url, { query: query }, function (data) { 
      labels = []; 
      mapped = {}; 
      $.each(data, function(i,item) { 
       mapped[item.label] = item.value; 
       labels.push(item.label); 
      }); 
      process(labels); 
     }); 
    } 
    ,updater: function (item) { 
     $('#client-id').val(mapped[item]); 
     return item; 
    } 
    ,items: 10 
    ,minLength: 2 
}); 

Tengo muchas cajas de búsqueda anticipada en la misma página. Cada cuadro de búsqueda tiene una identificación #xxx-search y una entrada oculta correspondiente con id #xxx-id. Me gustaría volver a utilizar el mismo código para todo, haciendo algo como esto:

$('#client-search, #endClient-search, #other-search').typeahead({ 

    ... 

    ,updater: function (item) { 
     var target = $(this).attr('id').split('-')[0] + '-id'; 
     $('#'+target).val(mapped[item]); 
     return item; 
    } 

    ... 

pensé que this se referirían al elemento de cuadro de texto en uso, pero al parecer no, porque me sale un error indefinido en Firebug:

$(this).attr("id") is undefined 

cuando uso this en lugar de $(this), me sale:

this.attr is not a function 

¿alguien puede ayudar a que esto wo ¿rk?


ACTUALIZACIÓN: LA RESPUESTA, Y MAS!

Gracias a la respuesta de benedict_w a continuación, esto no solo funciona perfectamente ahora, sino que también lo he hecho mucho mejor en términos de reutilización.

Esto es lo que mis <input> s parecen:

<input type="text" autocomplete="off" 
    id="client-search" 
    data-typeahead-url="/path/to/json" 
    data-typeahead-target="client-id"> 
<input type="hidden" id="client-id" name="client-id"> 

Aviso cómo el cuadro de búsqueda hace referencia a la identificación oculta. Aquí está el nuevo JS:

$(':input[data-typeahead-url]').each(function(){ 
    var $this = $(this); 
    $this.typeahead({ 
     source: function (query, process) { 
      $.get($this.attr('data-typeahead-url'), { query: query }, function (data) { 
       labels = []; 
       mapped = {}; 
       $.each(data, function(i,item) { 
        mapped[item.label] = item.value; 
        labels.push(item.label); 
       }); 
       process(labels); 
      }); 
     } 
     ,updater: function (item) { 
      $('#'+$this.attr('data-typeahead-target')).val(mapped[item]); 
      return item; 
     } 
     ,items: 10 
     ,minLength: 2 
    }); 
}); 
+0

estoy consiguiendo una pantalla de opciones "indefinido" en el menú desplegable cuando se utiliza esta solución. – Xeoncross

+0

@ Xeoncross: Tanto bootstrap como jQuery se han actualizado varias veces desde que se publicó esta pregunta. Es posible que ya no sea relevante para las versiones que está utilizando. –

Respuesta

24

Estás dentro de otra función por lo que necesita para guardar una referencia al elemento en el cierre exterior, esto se puede pasar en el controlador de eventos del cierre interior. Puede hacerlo utilizando una llamada $.each() para recorrer el selector guardando una referencia al elemento (esto) cada vez, p. Ej.

$('#client-search, #endClient-search, #other-search').each(function() { 
    var $this = $(this); 
    $this.typeahead({ 
     ... 

     ,updater: function (item) { 
      var target = $this.attr('id').split('-')[0] + '-id'; 
      $('#'+target).val(mapped[item]); 
      return item; 
     } 
     ... 
    }); 
+0

Encontrará más información sobre los cierres de JavaScript aquí: http://stackoverflow.com/questions/111102/how-do-javascript-closures-work –

+0

¡Muchas gracias, eso funcionó como un amuleto! –

+0

Estuve luchando con este problema durante 2 horas. ¡Salvaste mi día! –

4

La respuesta aceptada es buena, pero solo quería compartir una alternativa que en realidad no requiere el cierre exterior. Estoy usando bootstrap v2.3.1 y la entrada está disponible desde this.$element.

Ej:

$(':input[data-typeahead-url]').typeahead({ 
    source: function (query, process) { 
     $.get(this.$element.attr('data-typeahead-url'), { query: query }, function (data) { 
      labels = []; 
      mapped = {}; 
      $.each(data, function(i,item) { 
       mapped[item.label] = item.value; 
       labels.push(item.label); 
      }); 
      process(labels); 
     }); 
    } 
    ,updater: function (item) { 
     $('#'+this.$element.attr('data-typeahead-target')).val(mapped[item]); 
     return item; 
    } 
    ,items: 10 
    ,minLength: 2 
}); 
Cuestiones relacionadas