javascriptjquerytwitter-typeahead

Bind Id Value to Hidden Input via Typeahead


On my create form I have two input fields. One is hidden and the other is a text field.

@Html.HiddenFor(model => model.StateId)

<div class="form-group">
    @Html.Label("State", htmlAttributes: new { @class = "control-label col-md-2" })
    <div class="col-md-10">
        @Html.Editor("StateName", new { htmlAttributes = new { @id="StateName", @class = "form-control" } })
        @Html.ValidationMessageFor(model => model.StateId, "", new { @class = "text-danger" })
    </div>
</div>

In my text field, I am using typeahead to allow the user to select an option that matches what they're typing into the textbox. My script works for when the user does in fact select an option.. but it does not work if the user just types in the entire word. The text field is for states within the USA. So if the user types in t.. then states that contain that letter will appear for the user to select and once the user selects which state they want, the id of that state will be binded to the hidden input field.

But I know for my sake, if I were to type in Texas.. it's quicker for me to just type the word out, rather than taking my hands off of the keyboard and selecting the option. But if I do that.. and not select the option.. the id value is not binded to the hidden input field.

How do I still bind the id of the state that the user wants if they don't select from the auto-complete?

Here is my script:

<script>
    $(document).ready(function () {
        /*  For Auto Complete */

        var states = new Bloodhound({
            datumTokenizer: Bloodhound.tokenizers.obj.whitespace('state'),
            queryTokenizer: Bloodhound.tokenizers.whitespace,
            remote: {
                url: '/api/statesapi?query=%QUERY',
                wildcard: '%QUERY'
            }
        });

        $('#StateName').typeahead({
                highlight: true
            },
            {
                name: 'states',
                display: 'state',
                source: states,
                limit: 10
            }).bind('typeahead:select',
            function(ev, suggestion) {
                $("#StateId").val(suggestion.id);
            });

        /* ************************** */
    });
</script>

Solution

  • Since you always expect an ID based on the input, you might aswell just auto select the first suggestion.

    <script>
        $(document).ready(function () {
            /*  For Auto Complete */
    
            var states = new Bloodhound({
                datumTokenizer: Bloodhound.tokenizers.obj.whitespace('state'),
                queryTokenizer: Bloodhound.tokenizers.whitespace,
                remote: {
                    url: '/api/statesapi?query=%QUERY',
                    wildcard: '%QUERY'
                }
            });
    
            $('#StateName').typeahead({
                    highlight: true
                },
                {
                    name: 'states',
                    display: 'state',
                    source: states,
                    limit: 10
                }).bind('typeahead:select',
                function(ev, suggestion) {
                    $("#StateId").val(suggestion.id);
                }).bind("change", function(e) {
                    var first_suggestion = $(this).parent().find(".tt-suggestion:first-child")
                    if(first_suggestion.length!=0)
                        first_suggestion.trigger('click');
                    //else
                        // handle invalid input here
                });
    
            /* ************************** */
        });
    </script>
    

    Incase there are no suggestions shown, there is also no way of getting an ID for the input, so you could reset the input or display a warning...