2012-06-27 13 views
20

Sto cercando di utilizzare twitter bootstrap per ottenere i produttori dal mio DB.twitter bootstrap typeahead (metodo 'toLowerCase' di undefined)

Perché Twitter bootstrap typeahead non supporta le chiamate ajax Sto usando questo bivio:

https://gist.github.com/1866577

In quella pagina c'è questa comment che cita come fare esattamente quello che voglio fare. Il problema è che quando faccio funzionare il mio codice Continuo a ottenere:

Uncaught TypeError: Cannot call method 'toLowerCase' of undefined

Googled intorno e venne provato a cambiare il mio file jquery sia utilizzando il minified e non minified così come quello ospitato su Google Code e continuavo ottenendo lo stesso errore

Il mio codice attualmente è il seguente:

$('#manufacturer').typeahead({ 
    source: function(typeahead, query){ 
     $.ajax({ 
      url: window.location.origin+"/bows/get_manufacturers.json", 
      type: "POST", 
      data: "", 
      dataType: "JSON", 
      async: false, 
      success: function(results){ 
       var manufacturers = new Array; 
       $.map(results.data.manufacturers, function(data, item){ 
        var group; 
        group = { 
         manufacturer_id: data.Manufacturer.id, 
         manufacturer: data.Manufacturer.manufacturer 
        }; 
        manufacturers.push(group); 
       }); 
       typeahead.process(manufacturers); 
      } 
     }); 
    }, 
    property: 'name', 
    items:11, 
    onselect: function (obj) { 

    } 
}); 

sul campo URL ho aggiunto la

window.location.origin

per evitare problemi come già discusso su un'altra questione

anche prima che io fossi utilizzando $.each() e quindi deciso di utilizzare $.map() come consigliato Tomislav Markovski in un similar question

Qualcuno ha idea del perché continuo a ricevere questo problema ?!

Grazie

+0

Hai provato a eseguire il debug del codice JavaScript utilizzando Firebug o gli Strumenti di sviluppo F12 di IE per trovare esattamente dove sta cercando di chiamare 'toLowerCase()'? –

+0

@Cory utilizzando Google Chrome Ispezionare strumento ottengo che l'errore si trova sulla linea di codice di bootstrap Twitter 1664 Equivalente alla linea 124 sul [fork] (https://raw.github.com/gist/1866577/dd58c66be9dcb5b770e7f51a6cff324bec856021/bootstrap- typeahead.js) – mmoscosa

+0

@mmoscosa in Chrome Strumenti per sviluppatori molti errori javascript hanno un dropdown con altri errori interni e uno di quegli errori è la riga del codice in cui viene visualizzato tale errore. L'errore è associato a qualcosa nel bootstrap, ma dove l'errore si verifica effettivamente è nel tuo codice. –

risposta

6

AGGIORNATO/SGUARDO REVISIONE la questione: L'errore che lei ha citato "Impossibile chiamare il metodo 'toLowerCase' di non definito" venuto in mente quando ho usato l'estensione typeahead originale in bootstrap che non supporta AJAX. (come hai trovato) Sei sicuro che l'estensione originale di typeahead non si sta caricando, invece di quella modificata?

Sono stato con successo using this Gist of typeahead che è una leggera variazione su quello che hai citato. Una volta che sono passato a che Gist e ha confermato che i dati di input era buono (test che l'ingresso era un array di stringhe in un oggetto JS, il problema è andato via

Spero che questo aiuti


risposta originale.:

la ragione per cui l'errore si verifica perché il valore passato alla funzione typeahead matcher è indefinito. Questo è solo un effetto collaterale per il vero problema che si verifica da qualche parte tra l'input e che la funzione di abbinamento. ho il sospetto che l'array 'costruttori' ha un problema. Provalo prima per verificare di avere un array valido.

// It appears your array constructor is missing() 
// try the following in your binding code: 
var manufacturers = new Array(); 

Ecco cosa sto utilizzando per collegare l'input a typeahead. Ho confermato che funziona con la tua forcella typeahead modificata.

mio HTML:

<!-- Load bootstrap styles --> 
<link href="bootstrap.css" rel="stylesheet" type="text/css" /> 
... 

<input type="text" class="typeahead" name="Category" id="Category" maxlength="100" value="" /> 

... 
<!-- and load jQuery and bootstrap with modified typeahead AJAX code --> 
<script src="jquery-1.7.2.min.js" type="text/javascript"></script> 
<script src="bootstrap-modified-typeahead.js" type="text/javascript"></script> 

Il mio codice JavaScript vincolante:

// Matches the desired text input ID in the HTML 
var $TypeaheadInput = $("#Category"); 

// Modify this path to your JSON source URL 
// this source should return a JSON string array like the following: 
// string[] result = {"test", "test2", "test3", "test4"} 
var JsonProviderUrl = "../CategorySearch"; 

// Bind the input to the typeahead extension 
$TypeaheadInput.typeahead({ 
    source: function (typeahead, query) { 
     return $.post(JsonProviderUrl, { query: query }, function (data) { 
      return typeahead.process(data); 
     }); 
    } 
}); 
+0

'new Array' è una stenografia valida. JavaScript non richiede parentesi se non si forniscono argomenti a un costruttore. – Dennis

+0

Sono stato corretto sull'array. Alla ricerca di qualcosa che potrebbe rendere i dati indefiniti ... Non ho la possibilità di duplicare l'origine dati specifica, quindi non sono sicuro se c'è qualche altra discrepanza. Non credo che il codice typeahead sia un problema, perché funziona per me. –

+0

Ho risolto il problema "Can not call method toLowerCase" di undefined "giocando con l'ordine di caricamento degli script js (bootstrap, jquery e typeahed). – javanna

1

Gli oggetti costruttore non hanno un "nome" di proprietà, si dovrebbe cambiare

property: 'name', 

a

property: 'manufacturer', 
8

Nel mio caso, stavo ottenendo questo errore esatto, e si è scoperto che la versione di Bootstrap I in uso (2.0.4) non supportava il passaggio di una funzione all'impostazione source.

L'aggiornamento a Bootstrap 2.1.1 ha risolto il problema.

+0

Sto usando bootstrap v3.1.1 e sto affrontando lo stesso problema –

9

typeahead si aspettano un elenco di stringa come fonte

$('#manufacturer').typeahead({ 
    source : ["item 1", "item 2", "item 3", "item 4"] 
}) 

Nel tuo caso si desidera utilizzare con un elenco di oggetti. In questo modo si dovrà apportare alcune modifiche per rendere funziona

Questo dovrebbe funziona:

$('#manufacturer').typeahead({ 
    source: function(typeahead, query){ 
     $.ajax({ 
      url: window.location.origin+"/bows/get_manufacturers.json", 
      type: "POST", 
      data: "", 
      dataType: "JSON", 
      async: false, 
      success: function(results){ 
       var manufacturers = new Array; 
       $.map(results.data.manufacturers, function(data){ 
        var group; 
        group = { 
         manufacturer_id: data.Manufacturer.id, 
         manufacturer: data.Manufacturer.manufacturer, 

         toString: function() { 
          return JSON.stringify(this); 
         }, 
         toLowerCase: function() { 
          return this.manufacturer.toLowerCase(); 
         }, 
         indexOf: function (string) { 
          return String.prototype.indexOf.apply(this.manufacturer, arguments); 
         }, 
         replace: function (string) { 
          return String.prototype.replace.apply(this.manufacturer, arguments); 
         } 
        }; 
        manufacturers.push(group); 
       }); 
       typeahead.process(manufacturers); 
      } 
     }); 
    }, 
    property: 'manufacturer', 
    items:11, 
    onselect: function (obj) { 
     var obj = JSON.parse(obj); 

     // You still can use the manufacturer_id here 
     console.log(obj.manufacturer_id); 

     return obj.manufacturer; 
    } 
}); 
+0

Ha funzionato dopo aver apportato due correzioni. funzione (typeahead, query) modificata in (query, typehead). invece di typeahead.process (produttori), ha fornito typeahead (produttori); Correggimi se sbaglio. –

0

sono incappato in questo problema qualche tempo fa. Consiglio di ricontrollare la configurazione in cui si includono le librerie typeahead (tramite main.js, app.js o config.js).

In caso contrario, è possibile sovrascrivere lo latest Bootstrap version nella libreria dell'applicazione.

1

Hai provato a utilizzare le variabili di mappatura come nell'esempio seguente, devi usarlo quando hai più di una proprietà nel tuo oggetto;

source: function (query, process) { 
     states = []; 
     map = {}; 

     var data = [ 
      {"stateCode": "CA", "stateName": "California"}, 
      {"stateCode": "AZ", "stateName": "Arizona"}, 
      {"stateCode": "NY", "stateName": "New York"}, 
      {"stateCode": "NV", "stateName": "Nevada"}, 
      {"stateCode": "OH", "stateName": "Ohio"} 
     ]; 

     $.each(data, function (i, state) { 
      map[state.stateName] = state; 
      states.push(state.stateName); 
     }); 

     process(states); 
    } 
0

Prova di questo codice:

String.prototype.hashCode = function(){ 
var hash = 0; 
if (this.length == 0) return hash; 
for (i = 0; i < this.length; i++) { 
    char = this.charCodeAt(i); 
    hash = ((hash<<5)-hash)+char; 
    hash = hash & hash; // Convert to 32bit integer 
} 
return hash; 
}; 

var map_manufacter, result_manufacters; 
$('#manufacturer').typeahead({ 
source: function(typeahead, query){ 
    $.ajax({ 
     url: window.location.origin+"/bows/get_manufacturers.json", 
     type: "POST", 
     data: "", 
     dataType: "JSON", 
     async: false, 
     success: function(results){ 

      result_manufacter = [], map_manufacters = {}; 
      $.each(results.data.manufacturers, function(item, data){      
       map_manufacters[data.Manufacturer.manufacturer.hashCode()] = data; 
       result_manufacters.push(data.Manufacter.manufacter); 
      });    
      typeahead.process(result_manufacters);     
     } 
    }); 
}, 
property: 'name', 
items:11, 
onselect: function (obj) { 
    var hc = obj.hashCode(); 
    console.log(map_manufacter[hc]); 
} 

});

2

Nel mio caso ho avuto valori nulli nel mio array sorgente causando questo errore.

esempio inventato:

source : ["item 1", "item 2", null, "item 4"] 
Problemi correlati