bassjobsen / Bootstrap-3-Typeahead

The Typeahead plugin from Twitter's Bootstrap 2 ready to use with Bootstrap 3 and Bootstrap 4
1.68k stars 1.33k forks source link

it.toLowerCase is not a function #93

Open etairi opened 9 years ago

etairi commented 9 years ago

I'm using the script inside an ASP.NET MVC5 web application, and when I start typing inside the input element that uses typeahead, I get the following message in the console:

it.toLowerCase is not a function

Any idea what the problem might be?

bassjobsen commented 9 years ago

Could how tell me how your source have be defined? The it.toLowerCase is related to the change function and new since https://github.com/bassjobsen/Bootstrap-3-Typeahead/pull/84

For some reason this.displayText(item); is not defined (or not a string) in your situation. This could be a bug in the code or be related to your data source.

etairi commented 9 years ago

My script where I call the typeahead looks like this:

    $(function () {
        $("#service-manual").typeahead({
           source: function(request, response) {
               $.ajax({
                   url: "/Home/GetBusinessDesriptions",
                   dataType: "json",
                   data: {
                        state: $("#StateID").val(),
                        term: request.term
                    },
                   success: function (data) {
                        response(data);
                   }
             });
          },
         minLength: 2
     });
   });
bassjobsen commented 9 years ago

Thanks, could you also give me some example data returned from /Home/GetBusinessDesriptions?

etairi commented 9 years ago

Here is an example data:

{
    "id": 221,
    "value": "Business Management Consultants"
},
{
    "id": 221,
    "value": "Fuel Management"
},
{
    "id": 221,
    "value": "Financial Planning Consultants"
},
{
    "id": 221,
    "value": "Magnifying Glasses (Manufacturers)"
},
{
    "id": 221,
    "value": "Grinding Wheels (Manufacturers)"
}
bassjobsen commented 9 years ago

Thanks for posting the relevant data. Notice that the input should be an array of objects. The document should make clear that: "You can add all the properties you wish on your objects, as long as you provide a "name" attribute OR you provide your own displayText method."

So for your data set you will have to set the displayText: function(item){ return item.value;} option.

If also found an issue with select function and the displayText mentioned above (i already fix that: https://github.com/bassjobsen/Bootstrap-3-Typeahead/commit/33608b97dc63be3ec9f897210e29076a0ba72991)

Now you should be able to use the following code without any error:

$('.typeahead').typeahead(
{
items: 4,
source: [{
    "id": 221,
    "value": "Business Management Consultants"
},
{
    "id": 221,
    "value": "Fuel Management"
},
{
    "id": 221,
    "value": "Financial Planning Consultants"
},
{
    "id": 221,
    "value": "Magnifying Glasses (Manufacturers)"
},
{
    "id": 221,
    "value": "Grinding Wheels (Manufacturers)"
}],
 autoSelect: true,
 displayText: function(item){ return item.value;}
});
etairi commented 9 years ago

I changed the code like the one below, but now when I type I don't get any suggests, though I don't get any error messages too:

$("#service-manual").typeahead({
    items: 4,
    source: function(request, response) {
        $.ajax({
            url: "/Home/GetBusinessDesriptions",
            dataType: "json",
            data: {
                state: $("#StateID").val(),
                term: request.term
            },
            success: function (data) {
                response(data);
            }
        });
    },
    autoSelect: true,
    displayText: function (item) {
        return item.value;
    }
});

UPDATE:

Commenting out the autoSelect: true, part worked. I mean it started showing some suggestions, but when I select a suggestion, in the input box, instead of writing it's name, it writes [object Object]. And the other problem is that it just shows 4 suggestions, it is the same four each time.

bassjobsen commented 9 years ago

Also see http://jsfiddle.net/upasz7tq/1/ which seems to work well.

Commenting out the autoSelect: true, part worked. I mean it started showing some suggestions,

okay. currently i can reproduce it do not work with autoSelect: true but one could wonder if autoSelect works as expected. I will investigate that.

but when I select a suggestion, in the input box, instead of writing it's name, it writes [object Object].

The last version (after https://github.com/bassjobsen/Bootstrap-3-Typeahead/commit/33608b97dc63be3ec9f897210e29076a0ba72991) should fix that issue

And the other problem is that it just shows 4 suggestions, it is the same four each time.

the items: 4 option sets the number to (max) four. Does your URI deliver different results?

bassjobsen commented 9 years ago

The autoSelect option has been set to true by default (and seems to work right). So setting this option should not influence your results.

etairi commented 9 years ago

First of all, the above fix helped me solve the problem, when selecting an item from the list. Now it displays properly.

Though, the point is that even if I change the items value, for example, I changed it to 6, I still get 4 items, and they are the same ones always. But my URI returns different results according to what is written in the input box. For example, if I type just "et", then I should get different results, in comparison to when I type "an". But now, if I type "et", I get nothing, because the 4 items that it shows me, none of them include "et" sequence.

For example, the result of "Home/GetBusinessDesriptions?state=221&term=et" is the following JSON:

{
    "id": 221,
    "value": "Women's Apparel-Retail"
},
{
    "id": 221,
    "value": "Retail Shops"
},
{
    "id": 221,
    "value": "Ret Misc Vehicles Repair Services Plumbing/heating/air"
},
{
    "id": 221,
    "value": "Newspapers: Publishing, or Publishing and Printing (except Internet newspaper publishing)"
},
{
    "id": 221,
    "value": "Marketing Programs & Services"
}

And if I call it like this "Home/GetBusinessDesriptions?state=221&term=an", then the output is this:

{
    "id": 221,
    "value": "Business Management Consultants"
},
{
    "id": 221,
    "value": "Fuel Management"
},
{
    "id": 221,
    "value": "Financial Planning Consultants"
},
{
    "id": 221,
    "value": "Magnifying Glasses (Manufacturers)"
},
{
    "id": 221,
    "value": "Grinding Wheels (Manufacturers)"
}

I always limit the number of output two five, that's how my code is structured.

bassjobsen commented 9 years ago

okay what about the request.term in the data object? From the docs about the source function: " The function accepts two arguments, the query value in the input field and the process callback. "

So the first argument is the .val() of your #service-manual. So you should use term: request

etairi commented 9 years ago

I didn't catch exactly about which part you are talking. If you are talking about the part inside my AJAX call, where I have:

        data: {
            state: $("#StateID").val(),
            term: request.term
        },

The point is that it is defined like this because my GetBusinessDescriptions method is defined like: public JsonResult GetBusinessDesriptions(int state, string term)

My JS part is defined like that, because before typeahead I was using autocomplete from jQuery UI, but the point was that it was working all fine with retrieving and displaying the data, but when I was clicking the item that I wanted to select, nothing was happening with the input box, simply the text wasn't appearing in the input box. I searched online for a solution but nothing came out. Therefore, I thought I would use typeahead. Which solves the problem of selecting an item and displaying it in the input box, but there seems to be problem, with the retrieval of the data.

bassjobsen commented 9 years ago

Yes that's the right part. Have you tried changing term: request.term into term: request ?

etairi commented 9 years ago

Yes, that solved the problem! Thank you very much for your help.

One more quick question, the drop down list is not very nicely formatted, it looks like this: http://prntscr.com/5eq7kw

Do you have any idea about what might be the problem? Please note that I'm already including the bootstrap.css file.

bassjobsen commented 9 years ago

I can not be sure about that style issue. Most likely some of you other CSS overwrites the Bootstrap's .dropdown-menu class.

If you use Bootstrap's CSS also for other parts of your site, try to find the part that overwrite the .dropdown-menu class on the ul selector.

If you only need Bootstrap's CSS for the typeahead, try to compile a version with a higher specificity.

Less code:

@import "variables";
@import "mixins";
@import (reference) "dropdowns";

ul.typeahead.dropdown-menu {
&:extend(.dropdown-menu all);
a { text-decoration: none; }
}

which compiles into the following CSS code:

ul.typeahead.dropdown-menu {
  position: absolute;
  top: 100%;
  left: 0;
  z-index: 1000;
  display: none;
  float: left;
  min-width: 160px;
  padding: 5px 0;
  margin: 2px 0 0;
  list-style: none;
  font-size: 14px;
  text-align: left;
  background-color: #ffffff;
  border: 1px solid #cccccc;
  border: 1px solid rgba(0, 0, 0, 0.15);
  border-radius: 4px;
  -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
  box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
  background-clip: padding-box;
}
ul.typeahead.dropdown-menu.pull-right {
  right: 0;
  left: auto;
}
ul.typeahead.dropdown-menu .divider {
  height: 1px;
  margin: 9px 0;
  overflow: hidden;
  background-color: #e5e5e5;
}
ul.typeahead.dropdown-menu > li > a {
  display: block;
  padding: 3px 20px;
  clear: both;
  font-weight: normal;
  line-height: 1.42857143;
  color: #333333;
  white-space: nowrap;
}
ul.typeahead.dropdown-menu > li > a:hover,
ul.typeahead.dropdown-menu > li > a:focus {
  text-decoration: none;
  color: #262626;
  background-color: #f5f5f5;
}
ul.typeahead.dropdown-menu > .active > a,
ul.typeahead.dropdown-menu > .active > a:hover,
ul.typeahead.dropdown-menu > .active > a:focus {
  color: #ffffff;
  text-decoration: none;
  outline: 0;
  background-color: #337ab7;
}
ul.typeahead.dropdown-menu > .disabled > a,
ul.typeahead.dropdown-menu > .disabled > a:hover,
ul.typeahead.dropdown-menu > .disabled > a:focus {
  color: #777777;
}
ul.typeahead.dropdown-menu > .disabled > a:hover,
ul.typeahead.dropdown-menu > .disabled > a:focus {
  text-decoration: none;
  background-color: transparent;
  background-image: none;
  filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
  cursor: not-allowed;
}
.open > ul.typeahead.dropdown-menu {
  display: block;
}
.pull-right > ul.typeahead.dropdown-menu {
  right: 0;
  left: auto;
}
.dropup ul.typeahead.dropdown-menu,
.navbar-fixed-bottom .dropdown ul.typeahead.dropdown-menu {
  top: auto;
  bottom: 100%;
  margin-bottom: 1px;
}
@media (min-width: 768px) {
  .navbar-right ul.typeahead.dropdown-menu {
    left: auto;
    right: 0;
  }
}
ul.typeahead.dropdown-menu a,
ul.typeaheadul.typeahead.dropdown-menu a {
  text-decoration: none;
}
etairi commented 9 years ago

Thanks once more. I will check it out.

luizalbertobm commented 9 years ago

I solved this problem only updating the file bootstrap3-typeahead.min.js to the file in https://github.com/bassjobsen/Bootstrap-3-Typeahead/blob/master/bootstrap3-typeahead.min.js

I think most people can solve this way.

Mouradif commented 8 years ago

Hello @bassjobsen

I wonder WHY ON EARTH should I have a name attribute when I explicitly specify what attribute I want to display ?

$('#input').typeahead({ source: {VALID_JSON}, display: 'nom', val: 'id' });

chy996633 commented 8 years ago

I meet this problem too. Finally I found that if the name attribute of a item(belongs to source) appears to be "" ,which is an empty string, the displayText() method returns the hole item, and the toLowerCase() goes wrong.

xjtushilei commented 6 years ago

I meet this problem too. Finally I found that if the name attribute of a item(belongs to source) appears to be "" ,which is an empty string, the displayText() method returns the hole item, and the toLowerCase() goes wrong.

@chy996633 good job

quiet2 commented 5 years ago

work method displayText: function(item){ return item.value.toString(); }

ducthph commented 2 years ago

Thank you a lot