2

I am using the custom binding provided in How to create an auto-complete combobox?

I want to allow the user to either select a value from the list of suggestions or enter a value that is not in the list of suggestions. How can I get the value of the input into my observable field?

For example, if the user types 'smi' the autocomplete list will show Smith and other surnames beginning with 'smi', however, if they do not select an option from the list, I just want to set the value of my observable field to be 'smi'. At present, the only way the observable propety is set is when the user selects an item from the list of suggestions.

I have the following code (HTML):

<input type="text" data-bind="
                            value: surname,
                            jqAuto: { autoFocus: true },
                            jqAutoSource: surnames,
                            jqAutoQuery: surnameAutocomplete,
                            jqAutoValue: surname" 
            />

JavaScript view model (simplified):

var vm = {
    surnames: ko.observableArray(),
     surname: ko.observable(),
     surnameAutocomplete: function (searchTerm, result) {
        repository.surnameAutocomplete(searchTerm, result);
    };

Solution:

I amended the custom binding handler in two places:

  • init: function - added the following

        // New setting to allow / disallow a user to enter values that are in the autocomplete list.
        forceSelection = allBindings.jqAutoForceSelection;
    
  • options change function - amended to the following

    //on a change, make sure that it is a valid value or clear out the model value
    options.change = function (event, ui) {
        var currentValue = $(element).val();
    
        // Start: new code, check new setting on whether to force user to make a selection
        if (!forceSelection) {
            writeValueToModel(currentValue);
            return;
        }
        // End: new code
    
        var matchingItem = ko.utils.arrayFirst(unwrap(source), function (item) {
            return unwrap(inputValueProp ? item[inputValueProp] : item) === currentValue;
        });
    
        if (!matchingItem) {                
            writeValueToModel(null);
        }
    }
    

I also found that the first item in the autocomplete list was being automatically selected, but then noticed by setting autofocus: false solved my issue, e.g.,

<input type="text" data-bind="                                
                            jqAuto: { autoFocus: false }, /* This fixes the auto select issue */
                            jqAutoSource: surnames,
                            jqAutoQuery: surnameAutocomplete,
                            jqAutoValue: surname,
                            jqAutoForceSelection: false"
            />
Community
  • 1
  • 1
user2269352
  • 187
  • 2
  • 9

1 Answers1

1

If you look closely at the binding handler you're using, you will notice this section:

//on a change, make sure that it is a valid value or clear out the model value
    options.change = function(event, ui) {
        var currentValue = $(element).val();
        var matchingItem =  ko.utils.arrayFirst(unwrap(source), function(item) {
           return unwrap(item[inputValueProp]) === currentValue;  
        });

        if (!matchingItem) {
           writeValueToModel(null);
        }  

What this section of the binding handler essentially does is check if the text the user entered into the text field matches something in the autocomplete dropdown, and if it doesn't, it clears the model value (which it sounds like what you want to change).

You can either try deleting this section or extend it to suit your purposes.

Rune Vejen Petersen
  • 3,201
  • 2
  • 30
  • 46
  • I have amended my question to include a sample of the code I have. I would prefer to use the existing jqAuto binding handler written by RP Niemeyer as sometimes I want to show a different value in the textbox to the value stored in my observable property and his binding handler supports that. – user2269352 Apr 11 '13 at 12:40
  • Updated my answer now that I have more of an inkling about how you're implementing your Autocomplete – Rune Vejen Petersen Apr 11 '13 at 14:10
  • Thank you very much, it's now working exactly as I want and I have edited my question to include the final solution. – user2269352 Apr 12 '13 at 08:36