knockout.js 如何使用KnockoutJS和JQuery UI创建自动完成组合框

zpgglvta  于 2022-11-10  发布在  jQuery
关注(0)|答案(1)|浏览(116)

我一直在尝试根据this post中接受的响应创建一个自动完成下拉列表,但是这个自动完成下拉列表根本就没有显示出来。可能是因为这个响应是9年前的,也可能是我做错了什么。我已经尝试了我遇到的所有建议。有没有一个更新的方法可以使用jquery 1.12.3版创建这个组合框,jquery-ui版本1.12.1和knockoutjs版本3.4.1?
对我来说,绑定似乎并没有真正发生,因为我可以将自定义绑定重命名为“jqAuto 1”而不是“jqAuto”,即使“jqAuto 1”没有在任何地方定义,也不会有错误。为什么没有选择它呢?
这是我的代码。注意JS脚本在一个独立的父解决方案中,与CSHTML和TS文件不同。浏览器仍然会找到并执行JS脚本。

简体中文HTML

<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" />

技术支持

// 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");

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);
})();
roqulrg3

roqulrg31#

我没有完全理解你的问题。但是敲除和UI完成无关。请看一个简单的使用UI完成的例子。

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);
        });
    };

}

相关问题