Search code examples
javascriptajaxtypeahead.jstwitter-typeaheadbloodhound

Typeahead search with Post ajax call not working


This is my sample data that I am getting through POST api call that I have to use in typeahead search in MVC View.

{
    "MyWrapper": {
        "lstCourses": [
            {
                "CourseId": 1,
                "CourseName": "BCA"
            },
            {
                "CourseId": 2,
                "CourseName": "MCA"
            },
            {
                "CourseId": 3,
                "CourseName": "Btech"
            },
            {
                "CourseId": 4,
                "CourseName": "Mtech"
            },
            {
                "CourseId": 5,
                "CourseName": "MCom"
            },
            {
                "CourseId": 6,
                "CourseName": "Phd"
            },
            {
                "CourseId": 7,
                "CourseName": "Physics"
            },
            {
                "CourseId": 8,
                "CourseName": "philosophy"
            }
        ]
    }
}

I want to show course name in typeahead search and for this I a using typeaahead.js and bloodhound

This is my html code and my issue is CourseNames are not coming as suggestions in text box.

<link href="~/Content/bootstrap.css" rel="stylesheet" />
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script src="~/Scripts/typeaahead.js"></script>
<div id="bloodhound">
    <input class="typeahead" type="text" placeholder="States of USA">
</div>

<script>


    var courses = new Bloodhound({
        datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'),
        queryTokenizer: Bloodhound.tokenizers.whitespace,

        remote: {
            url: 'http://localhost:54518/api/Myapi#%QUERY',
           wildcard: '%QUERY',
            transport: function (opts, onSuccess, onError) {
                var url = opts.url.split("#")[0];
                var query = opts.url.split("#")[1];
                var result;

                    $.ajax({
                        url: url,
                        data: "value=" + query,
                        type: "POST",
                        success: function (data) { return data.MyWrapper.lstCourses; },
                        error: onError,
                    })


            }
        }
    });

    courses.initialize();
    $('input').typeahead(null, {
        name: 'courses',
        displayKey: 'value',
        source: courses,
        templates: {
            empty: [
             '<div class="empty-message">',
             'no results found',
             '</div>'
            ].join('\n'),
            suggestion: function (data) {
                console.log (data);
                return '<p><strong>' + data.CourseId + '  </strong> - ' + data.CourseName + '</p>';

            }
        }


    });




</script>

Main issue I am facing in handling nested objects to set as source.Can anyone please put me on right path?any relevant links?


Solution

  • I can think of two things that might fix it for you.

    You can try changing the initialization for the typeahead so that the display key is a property in your data:

    name: 'courses',
    displayKey: 'CourseName',
    source: courses,
    

    You can also try adding a filter method to the remote. I use the filter method in my remote options to change the dataset I get to something more easily used by the typeahead:

    remote: {
            filter: function (data) {
                if (data) {
                    return $.map(data, function (object) {
                        return { id: object.id, value: object.name};
                    });
                } else {
                    return {};
                }
            }
        }
    

    In your case, you would need to check the data you are returning and probably use data.MyWrapper.lstCourses. But that is something you can easily check using the dev tools in your browser. If you use the filter method, you can leave your displayKey setting as "value".