KnockoutJS - 将输入值与数据列表值相关联 [英] KnockoutJS - Linking value from a input to a datalist value

查看:141
本文介绍了KnockoutJS - 将输入值与数据列表值相关联的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在根据ko observable生成 datalist 选项。

I'm generating a datalist options based on a ko observable.

function Company(company) {
    this.id = company.Id;
    this.name = company.Name;
    this.state = company.State.name;
}


var self = this;
self.companies = ko.observable();
$.get('...', {}, function(result) {

    ko.utils.arrayForEach(result, function(company) {
        self.companies.push(new Company(ko.toJS(company)));
    });
});

HTML:

<input type="text" data-bind="value: selectedCompany" list="companiesList" />
<datalist id="companiesList" data-bind="foreach: companies">
    <option data-bind="value: name, text: state"></option>
</datalist>

好的,这是交易:在公司 function,我存储该公司的Id。我想做的事?能让我将Id值链接到selectedCompany变量而不是名称的东西?我想显示name属性,但我需要存储Id。

Ok, here's the deal: in the Company function, I store the Id from that company. What I want to do? Something that able me to link the Id value to selectedCompany variable instead the name? I want to display the name property, but I need to store the Id.

有没有办法做到这一点?
谢谢大家!

Is there a way to do this? Thank you all!

推荐答案


我想显示名称属性,但是我需要存储Id。

I want to display the name property, but I need to store the Id.

由于目前没有针对HTML5的Knockout绑定< datalist> ,我做了一个。

Since there is currently no Knockout binding for HTML5 <datalist>, I made one.

我试图从选择尽可能多地借款绑定,因此支持选项 optionsText optionsValue 。您可以通过 value 指定目标可观察对象。

I tried to borrow as much as I could from the select binding, so there is support for options, optionsText and optionsValue. You can specify a target observable via value.

ko.bindingHandlers.datalist = (function () {
    function getVal(rawItem, prop) {
        var item = ko.unwrap(rawItem);
        return item && prop ? ko.unwrap(item[prop]) : item;
    }

    function findItem(options, prop, ref) {
        return ko.utils.arrayFirst(options, function (item) {
            return ref === getVal(item, prop);
        });
    }
    return {
        init: function (element, valueAccessor, allBindingsAccessor) {
            var setup = valueAccessor(),
                textProperty = ko.unwrap(setup.optionsText),
                valueProperty = ko.unwrap(setup.optionsValue),
                dataItems = ko.unwrap(setup.options),
                myValue = setup.value,
                koValue = allBindingsAccessor().value,
                datalist = document.createElement("DATALIST");

            // create an associated <datalist> element
            datalist.id = element.getAttribute("list");
            document.body.appendChild(datalist);

            // when the value is changed, write to the associated myValue observable
            function onNewValue(newVal) {
                var dataItems = ko.unwrap(setup.options),
                    selectedItem = findItem(dataItems, textProperty, newVal),
                    newValue = selectedItem ? getVal(selectedItem, valueProperty) : void 0;

                if (ko.isWriteableObservable(myValue)) {
                    myValue(newValue);
                }
            }

            // listen for value changes
            // - either via KO's value binding (preferred) or the change event
            if (ko.isSubscribable(koValue)) {
                koValue.subscribe(onNewValue);
            } else {
                ko.utils.registerEventHandler(element, "change", function () {
                    onNewValue(this.value);
                });
            }

            // init the element's value
            // - either via the myValue observable (preferred) or KO's value binding
            if (ko.isObservable(myValue) && myValue()) {
                element.value = getVal(findItem(dataItems, valueProperty, myValue()), textProperty);
            } else if (ko.isObservable(koValue) && koValue()) {
                onNewValue(koValue());
            }
        },
        update: function (element, valueAccessor) {
            var setup = valueAccessor(),
                datalist = element.list,
                dataItems = ko.unwrap(setup.options),
                textProperty = ko.unwrap(setup.optionsText);

            // rebuild list of options when an underlying observable changes
            datalist.innerHTML = "";
            ko.utils.arrayForEach(dataItems, function (item) {
                var option = document.createElement("OPTION");
                option.value = getVal(item, textProperty);
                datalist.appendChild(option);
            });
            ko.utils.triggerEvent(element, "change");
        }
    };
})();

我希望我能做到这一点。我们欢迎更正和改进建议。

I hope I got most of this right. Corrections and improvement suggestions are welcome.

您可以这样使用它:

<input list="company" data-bind="datalist: {
    options: companies, 
    optionsValue: 'id', 
    optionsText: 'name', 
    value: selectedCompany
}" />

注意。


  • 无需在HTML中创建单独的< datalist> 。自定义绑定为您完成此操作。

  • 但是,您必须提供 list =属性< input> 元素。到目前为止,我发现在JavaScript中无法动态设置它。

  • value 是可选的,但是如果你提供它,它必须是一个可观察的。

  • 您仍然可以在 datalist 值绑定>。它将包含< input> 显示的任何文本(没有惊喜)。但是,写入内置值也会更新 datalist 值,反之亦然。

  • datalist 值具有优先权,并将覆盖视图模型init上的内置值。之后它们保持同步。

  • 选项应该是一个对象的数组(普通的或可观察的) - 本例中的公司) 。

  • optionsText optionsValue 是应映射到您的属性的字符串选项。

  • 您不必使用 optionsValue - 在这种情况下,整个对象(单个公司)将存储在。我希望仅存储ID。

  • 目前,设置会对更改事件作出反应。这意味着在您离开输入字段之前,您的视图模型不会更新。

  • 在Chrome 32,YMMV上测试。正如我所说,欢迎提出意见和更正。

  • There is no need to create a separate <datalist> in the HTML. The custom binding does that for you.
  • You must, however, supply the list="" attribute of the <input> element. I found no way of dynamically setting that in JavaScript so far.
  • value is optional, but if you supply it, it must be an observable.
  • You can still use the original value binding outside of datalist. It will contain whatever text the <input> displays (no surprises there). However, writing to the built-in value also updates the datalist value, and the other way around.
  • The datalist value has precedence and will overwrite the built-in value upon view model init. After that they stay in sync.
  • options should be an array (plain old or observable) of objects — companies in this case).
  • optionsText and optionsValue are strings that should map to properties on your options.
  • You do not have to use optionsValue — in that case the entire object (a single company) would be stored in value. I would prefer that over storing only the ID.
  • Currently the set-up reacts to the change event. That means your view model won't update until you leave the input field.
  • Tested on Chrome 32, YMMV. As I said, comments and corrections are welcome.

这是一个小提琴,显示了这一点:http://jsfiddle.net/GJ4h4/3/

Here is a fiddle that shows this: http://jsfiddle.net/GJ4h4/3/

这篇关于KnockoutJS - 将输入值与数据列表值相关联的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆