Search code examples
c#asp.net-mvcasp.net-mvc-4twitter-bootstrapbootstrap-typeahead

MVC Bootstrap typeahead HtmlHelper


I'm fairly new with MVC and working on a MVC4 website with Twitter's Bootstrap and we need a HtmlHelper for TypeAhead.

I obtained code for a HtmlHelper for Twitter's Bootstrap here:

public static MvcHtmlString TypeaheadFor<TModel, TValue>(
    this HtmlHelper<TModel> htmlHelper, 
    Expression<Func<TModel, TValue>> expression, 
    IEnumerable<string> source, 
    int items = 8)
{
    if (expression == null)
        throw new ArgumentNullException("expression");

    if (source == null)
        throw new ArgumentNullException("source");

    var jsonString = new JavaScriptSerializer().Serialize(source);

    return htmlHelper.TextBoxFor(
        expression, 
        new { 
            autocomplete = "off", 
            data_provide = "typeahead", 
            data_items = items, 
            data_source = jsonString 
        }
    );
}

I also wrote the following code to provide the JSON for the typeahead:

        public JsonResult Autocomplete(string input) {
        var model = db.Users
                      .Select(g => new {
                          label = g.Name.StartsWith(input)
                      });
        return Json(model, JsonRequestBehavior.AllowGet);
    }

As it is now, i provide the HtmlHelper with a IEnumerable< string> to populate the suggestion box. I can't figure out how to use my own JsonResult for this. It also needs to be dynamic because we'll need the HtmlHelper on multipe instances on the website with several different item sources, all pulled from the database using EF.

What I don't like about this solution is that the contents from the IEnumerable< string> are shown in the html source, easily readable for the visitor.

Is there a way to have a HtmlHelper for Twitters typeahead.js and call JsonResult as the item source, and not have the JsonResults coded in the html printed to the end user?


Solution

  • I think it would be much easier to just use typeahead directly.

    $(function() {
        // get your list
        $.getJSON('/Controller/Autocomplete', function (allData) {
             $('#your-element').typeahead({source: allData});
        };
    });
    

    You could, of course, turn this into a helper, but I think it's easier this way. Note: I didn't test this code, so please forgive any bugs, but hopefully it gives you the idea. Since the action is called using AJAX, it won't be in the raw page source as well. You could also change the source to a function call and periodically update the data from your action as needed.