Javascript 如何使用KnockoutJS和jqueryui创建自动完成组合框

Javascript 如何使用KnockoutJS和jqueryui创建自动完成组合框,javascript,jquery,jquery-ui,knockout.js,jquery-ui-autocomplete,Javascript,Jquery,Jquery Ui,Knockout.js,Jquery Ui Autocomplete,我一直在尝试根据中接受的响应创建一个自动完成下拉列表,但是自动完成下拉列表根本没有出现。这可能是因为反应是9岁,也可能是我做错了什么。我已经尝试了我遇到的所有建议。是否有更新的方法使用jquery版本1.12.3、jquery ui版本1.12.1和knockoutjs版本3.4.1创建此组合框 对我来说,似乎绑定并没有真正发生,因为我可以将自定义绑定重命名为“jqAuto1”而不是“jqAuto”,并且不会出现错误,即使“jqAuto1”在任何地方都没有定义。为什么不把它捡起来 这是我的密码。

我一直在尝试根据中接受的响应创建一个自动完成下拉列表,但是自动完成下拉列表根本没有出现。这可能是因为反应是9岁,也可能是我做错了什么。我已经尝试了我遇到的所有建议。是否有更新的方法使用jquery版本1.12.3、jquery ui版本1.12.1和knockoutjs版本3.4.1创建此组合框

对我来说,似乎绑定并没有真正发生,因为我可以将自定义绑定重命名为“jqAuto1”而不是“jqAuto”,并且不会出现错误,即使“jqAuto1”在任何地方都没有定义。为什么不把它捡起来

这是我的密码。请注意,JS脚本与CSHTML和TS文件位于单独的父解决方案中。浏览器仍然会查找并执行JS脚本

CSHTML

<input class="form-control form-control-xs" data-bind="value: companyName, jqAuto: { autoFocus: true }, jqAutoSource: myComp, jqAutoValue: mySelectedGuid, jqAutoSourceLabel: 'displayName', jqAutoSourceInputValue: 'coname', jqAutoSourceValue: 'id'" placeholder="Type Company Name and select from list" />

TS

// For list of Companies
class Comp {
    _id: KnockoutObservable<string>;
    _coname: KnockoutObservable<string>;
    _coid: KnockoutObservable<string>;

    constructor(id: string, coname: string, coid: string) {
        this._id = ko.observable(id);
        this._coname = ko.observable(coname);
        this._coid = ko.observable(coid);
    }
}

myComp: KnockoutObservableArray<Comp>;
mySelectedGuid: KnockoutObservable<string>;
displayName: KnockoutComputed<string>;

...

this.myComp = ko.observableArray([
            new Comp("1", "Company 1", "CO1"),
            new Comp("2", "Company 2", "CO2"),
            new Comp("3", "Company 3", "CO3"),
            new Comp("4", "Company 4", "CO4"),
            new Comp("5", "Company 5", "CO5")
        ]);

this.companyName = ko.validatedObservable<string>("");
this.displayName = ko.computed(function () {
            return this.myComp.coname + " [" + this.myComp.coid + "]";
        }, this);
this.mySelectedGuid = ko.observable("5");
//用于公司列表
班级薪酬{
_id:可观察到的敲除;
_coname:可观察到的敲除;
_coid:可观察到的敲除;
构造函数(id:string,coname:string,coid:string){
这个._id=ko.可观察(id);
这是可观察的(coname);
这是可观测的(coid);
}
}
mycop:敲除耳环;
mySelectedGuid:knockoutobserved;
显示名称:KnockoutComputed;
...
this.mycop=ko.array([
新公司(“1”、“公司1”、“CO1”),
新公司(“2”、“公司2”、“二氧化碳”),
新公司(“3”、“公司3”、“CO3”),
新公司(“4”、“公司4”、“CO4”),
新公司(“5”、“公司5”、“CO5”)
]);
this.companyName=ko.validatedObservable(“”);
this.displayName=ko.computed(函数(){
返回this.mycop.coname+“[”+this.mycop.coid+“]”;
},这个);
this.mySelectedGuid=ko.可观察(“5”);
JS 链接的帖子里有很多内容

(function () {
    var global = this || (0, eval)('this'),
        document = global['document'],
        moduleName = 'knockout-binding-jqauto',
        dependencies = ['knockout', 'jquery'];

    var moduleDance = function (factory) {
        // Module systems magic dance.

        if (typeof define === "function" && define["amd"]) {
            define(moduleName, dependencies.concat('exports'), factory);
        } else {
            // using explicit <script> tags with no loader
            global.CPU = global.CPU || {};
            factory(global.ko, global.Globalize);
        }
    };

    var factory = function (ko, $) {

        ko.bindingHandlers.jqauto = {
            init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
                var options = valueAccessor() || {},
                    allBindings = allBindingsAccessor(),
                    unwrap = ko.utils.unwrapObservable,
                    modelValue = allBindings.jqAutoValue,
                    source = allBindings.jqAutoSource,
                    valueProp = allBindings.jqAutoSourceValue,
                    inputValueProp = allBindings.jqAutoSourceInputValue || valueProp,
                    labelProp = allBindings.jqAutoSourceLabel || valueProp;

                //function that is shared by both select and change event handlers
                function writeValueToModel(valueToWrite) {
                    if (ko.isWriteableObservable(modelValue)) {
                        modelValue(valueToWrite);
                    } 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) {
                    writeValueToModel(ui.item ? ui.item.actualValue : null);
                };

                //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();
                    alert(currentValue);
                    var matchingItem = ko.utils.arrayFirst(unwrap(source), function (item) {
                        return unwrap(inputValueProp ? item[inputValueProp] : item) === currentValue;
                    });

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


                //handle the choices being updated in a DO, to decouple value updates from source (options) updates
                var mappedSource = ko.dependentObservable(function () {
                    mapped = ko.utils.arrayMap(unwrap(source), function (item) {
                        var result = {};
                        result.label = labelProp ? unwrap(item[labelProp]) : unwrap(item).toString();  //show in pop-up choices
                        result.value = inputValueProp ? unwrap(item[inputValueProp]) : unwrap(item).toString();  //show in input box
                        result.actualValue = valueProp ? unwrap(item[valueProp]) : item;  //store in model
                        return result;
                    });
                    return mapped;
                }, null, { disposeWhenNodeIsRemoved: element });

                //whenever the items that make up the source are updated, make sure that autocomplete knows it
                mappedSource.subscribe(function (newValue) {
                    $(element).autocomplete("option", "source", newValue);
                });

                options.source = mappedSource();

                //initialize autocomplete
                $(element).autocomplete(options);

            },

            update: function (element, valueAccessor, allBindings, viewModel) {
                //update value based on a model change
                var allBindings = allBindingsAccessor(),
                    unwrap = ko.utils.unwrapObservable,
                    modelValue = unwrap(allBindings.jqAutoValue) || '',
                    valueProp = allBindings.jqAutoSourceValue,
                    inputValueProp = allBindings.jqAutoSourceInputValue || valueProp;

                //if we are writing a different property to the input than we are writing to the model, then locate the object
                if (valueProp && inputValueProp !== valueProp) {
                    var source = unwrap(allBindings.jqAutoSource) || [];
                    var modelValue = ko.utils.arrayFirst(source, function (item) {
                        return unwrap(item[valueProp]) === modelValue;
                    }) || {};  //probably don't need the || {}, but just protect against a bad value          
                }

                //update the element with the value that should be shown in the input
                $(element).val(modelValue && inputValueProp !== valueProp ? unwrap(modelValue[inputValueProp]) : modelValue.toString());
            }

        }
    };

    moduleDance(factory);
})();
(函数(){
var global=this | |(0,eval)(“this”),
document=全局['document'],
moduleName='knockout binding jqauto',
依赖项=['knockout','jquery'];
var moduleDance=功能(工厂){
//模块系统魔术舞蹈。
if(typeof define==“函数”&&define[“amd”]){
定义(moduleName,dependencies.concat('exports'),factory);
}否则{
//使用无加载程序的显式标记
global.CPU=global.CPU | |{};
工厂(global.ko,global.Globalize);
}
};
变量工厂=函数(ko,$){
ko.bindingHandlers.jqauto={
init:函数(元素、valueAccessor、allBindings、viewModel、bindingContext){
var options=valueAccessor(),
allBindings=allBindingsAccessor(),
展开=ko.utils.unwrapObservable,
modelValue=allBindings.jqAutoValue,
source=allBindings.jqAutoSource,
valueProp=allBindings.jqAutoSourceValue,
inputValueProp=allBindings.jqAutoSourceInputValue | | valueProp,
labelProp=allBindings.jqAutoSourceLabel | | valueProp;
//由选择和更改事件处理程序共享的函数
函数writeValueToModel(valueToWrite){
if(ko.isWriteableObservable(modelValue)){
模型值(valueToWrite);
}else{//写入不可见的
if(所有绑定['''''''''''''''''''''''''''''''''''.'写入程序'.''和所有绑定[''''''''''''.'写入程序'.''写入程序'.''jqAutoValue'.]
所有绑定[''u ko_property'u writers']['jqAutoValue'](valueToWrite);
}
}
//在选择项上,将适当的值写入模型
options.select=函数(事件、用户界面){
writeValueToModel(ui.item?ui.item.actualValue:空);
};
//在进行更改时,请确保它是有效值或清除模型值
options.change=函数(事件、用户界面){
var currentValue=$(元素).val();
警报(当前值);
var matchingItem=ko.utils.arrayFirst(展开(源)、函数(项){
返回展开(inputValueProp?项[inputValueProp]:项)==currentValue;
});
如果(!匹配项){
writeValueToModel(空);
}
}
//处理DO中正在更新的选项,以将值更新与源(选项)更新解耦
var mappedSource=ko.dependenttobservable(函数(){
mapped=ko.utils.arrayMap(展开(源)、函数(项){
var result={};
result.label=labelProp?展开(项[labelProp]):展开(项).toString();//在弹出选项中显示
result.value=inputValueProp?展开(项[inputValueProp]):展开(项).toString();//显示在输入框中
result.actualValue=valueProp?展开(项[valueProp]):项;//存储在模型中
返回结果;
});
返回映射;
},null,{dispewhenNodeisremoved:element});
//每当组成源的项目被更新时,确保autocomplete知道它
订阅(函数(newValue){
$(元素)。自动完成(“选项”,“源”,newValue);
});
options.source=mappedSource();
//初始化自动完成
$(元素)。自动完成(选项);
},
更新:函数(元素、valueAccessor、allBindings、viewModel){
async function autocomplete() {
    const sthings= await getSthings(); //gets json array, or ajax call, this is a promise
    $("#sthHighlightSearch").autocomplete({
        source: sthings
    });
    //This is an extension method for autocomplete
    //Should filter the list with starts with characters written in the autocomplete
    $.ui.autocomplete.filter = function (array, term) {
        var matcher = new RegExp("^" + $.ui.autocomplete.escapeRegex(term), "i");
        return $.grep(array, function (value) {
            return matcher.test(value.label || value.value || value);
        });
    };

}