如何使用KnockoutJS将所选字段的文本更改为大写?

时间:2014-07-21 17:24:17

标签: javascript knockout.js

我的应用程序所有者希望选择的文本字段为大写,就像大写锁定已打开一样。我正在使用具有这些字段的observable的KnockoutJS视图模型。有没有办法可以将任何用户输入的文本转换为大写?

我在我想要更改的控件上放了一个input事件,但发现尽管它有效,但是observables没有更新。

<input type="text" maxlength="80" data-bind="value: colorName, disable: $parent.isReadOnly, event: { 'input': toUpper }" />

toUpper: function (d, e) {
    if (e.target) {
        if (e.target.value) {
            e.target.value = e.target.value.toUpperCase();
        }
    }
}

我一直在考虑将ucase CSS类放在我希望成为大写的控件上,然后在客户端或服务器上,将这些字段保存为大写。

.ucase {
    text-transform: uppercase;
}

2 个答案:

答案 0 :(得分:9)

你可以扩展你的观察力 -

<input data-bind="value: colorName, valueUpdate:'afterkeydown'" />

ko.extenders.uppercase = function(target, option) {
    target.subscribe(function(newValue) {
       target(newValue.toUpperCase());
    });
    return target;
};

var colorName = ko.observable().extend({ uppercase: true });

小提琴示例 - http://jsfiddle.net/kbFwK/

基本上每当值发生变化时,它都会将observable的值转换为大写。

这里的缺点是它实际上会更改值并以这种方式存储它。您可以始终将计算属性添加到observable上,仅用于显示目的。您可以使用ko.computed,自定义绑定处理程序(因为它仅用于演示)或类似的东西来实现。如果这更符合您的要求,请通过评论告诉我。

修改

更新了afterkeydown - http://jsfiddle.net/kbFwK/2/

答案 1 :(得分:1)

这是我编写的自定义绑定,可确保输入字段和可观察字段均为大写。它应该像textInput绑定一样工作。

ko.bindingHandlers.textInputUpperCase = {
    init: (element, valueAccessor) => {
        const observable = valueAccessor();
        let preventDoubleUpdate = false;

        function update(newValue) {
            if (preventDoubleUpdate) {
                preventDoubleUpdate = false;
            } else {
                switch(typeof newValue) {
                    //Undefined value will be displayed as empty in the input field.
                    case 'undefined':
                        element.value = '';
                        break;
                    //String value will be converted to upper case.
                    case 'string':
                        const upperCase = newValue.toLocaleUpperCase();
                        //Check if input field matches the observable. If not the change was made directly to the observable.
                        const match = element.value.toLocaleUpperCase() === upperCase;
                        //Remember the cursor position.
                        const selectionStart = element.selectionStart;
                        const selectionEnd = element.selectionEnd;
                        //Update the input text (will move the cursor to the end of the text).
                        element.value = upperCase;
                        //Move the cursor to it's original position if the change came from the input field.
                        if (match) {
                            element.selectionStart = selectionStart;
                            element.selectionEnd = selectionEnd;
                        }
                        //Update the observable if necessary and make sure it won't do a double update.
                        if (newValue !== upperCase) {
                            preventDoubleUpdate = true;
                            observable(upperCase);
                        }
                        break;
                    default:
                        element.value = newValue;
                }
            }
        }

        //Run the update function each time the observable has been changed
        observable.subscribe(update);

        //Initiate the observable and input
        update(observable());

        //Update the observable on changes of the text in the input field
        element.addEventListener('input', event => {
            observable(event.target.value);
        });
    }
};

一个小警告。如果您写给观察者,它将两次通知其他订户。首先,当您写入它时,然后当它变成大写时。