0

I'm using the KnockoutJS Autocomplete code found here:

How to create an auto-complete combobox?

Generally it's working just fine. I'm using a JQuery Ajax call to get the data for the Autocomplete. When I type into the input field, then select a value from the list, the corresponding value is set in the Knockout ViewModel. However, I can't get it to set the selected text value from the autocomplete.

(This is to be able to look up SIC numbers, given a partial description)

I have defined:

function Sic(SICCode, SICDescription) {
    var self = this;
    self.SICCode = ko.observable(SICCode);
    self.SICDescription = ko.observable(SICDescription);
}

My ViewModel has:

    self.SICCode = ko.observable("");
    self.SICDescription = ko.observable("");
    self.SicCodes = ko.observableArray();

and the lookup function is:

    self.getSicCode = function (searchTerm, sourceArray) {
        $.getJSON(_serviceURL + "/GetSicFromDescription/" + searchTerm, function (data) {
            if (data.length > 0) {
                var result = [];
                $.map(data, function (item) {
                    result.push(new Sic(item.SicCode, item.Description));
                });
                sourceArray(result);
            }
        });
    }

In the input tag (it's actually a .NET page (and actually a DotNetNuke custom module, but that doesn't matter for this) ) I have:

    <div>SIC:<br />
        <input type="text" maxlength="30" 
            data-bind="value: SICDescription, 
            jqAuto: {minLength: 3, autoFocus: true}, jqAutoQuery:getSicCode,
            jqAutoSource: SicCodes, jqAutoSourceLabel: SICDescription, 
            jqAutoValue: SICCode, jqAutoSourceInputValue: 'SICDescription', 
            jqAutoSourceValue: 'SICCode'" />
        <span data-bind="text: SICCode"></span>
    </div>

(I've tried with and without the value: binding) Typing into the input box will correctly do the lookup and present the list of matching items. I can then select one and see the corresponding number in the span.

However, when I then click a button that then sends the ViewModel data to the server, the self.SICDescription() is empty... self.SICCode() contains the correct value.

So, how do I get the selected description populated into the ViewModel? I would have assumed using the value binding for the input field should have done the trick. But no go.

Is there anyway to do what I need, or am I going to have to do some work around (looping through the array of returned values and pluck out the right description)?

Thanks.

Community
  • 1
  • 1
John T
  • 2,687
  • 2
  • 27
  • 36

1 Answers1

1

Because the knockout observables are functions you can store any number of objects in them. I will store your description value in the SICCode. Change the binding code's writeValueToModel & option.select part like this :

 //function that is shared by both select and change event handlers
        function writeValueToModel(valueToWrite,name) {
            if (ko.isWriteableObservable(modelValue)) {
               modelValue(valueToWrite);         
               modelValue.nameProp = ko.observable(name);             
            } else {  //write to non-observable
               if (allBindings['_ko_property_writers'] && allBindings['_ko_property_writers']['jqAutoValue'])
                        allBindings['_ko_property_writers']['jqAutoValue'](valueToWrite );    
            }
        }
        
        //on a selection write the proper value to the model
        options.select = function(event, ui) {
            var actualValue = ui.item ? ui.item.actualValue : null;
            var value = ui.item ? ui.item.value : null;
            writeValueToModel(actualValue,value);
        };

I am storing your description value in the SICCode with in another observable name like 'nameProp'.

You can get its description like this SICCode.nameProp();

Actually for your case you can get the description value by calling $("#yourInputID").val()

But for more complex situations you can use the above code.

JSFIDDLE DEMO

Click the test button after select the item.

Community
  • 1
  • 1
Luffy
  • 2,257
  • 16
  • 24
  • That's awesome, that does give me access to the description. One other change I made was in the options.change = function (event, ui) {... adding the second parameter to the call to writeValueToModel(NULL, NULL); – John T Feb 13 '13 at 13:50
  • Now, I need to be able to add that to the JSON being sent to the server. I'm using something like: ko.toJSON(self,['ZipCode', 'City', 'State', 'SICCode']) to build the JSON, to not include unnecessary viewModel values. Just need to be able to add the description to that list... Thanks. – John T Feb 13 '13 at 13:52
  • Ok.. I did it the brute force method, I just built a new object and used that to send back to the server. I can live with that. Thanks! – John T Feb 13 '13 at 14:00