最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How To Change Text For Selected Fields To Uppercase Using KnockoutJS? - Stack Overflow

programmeradmin3浏览0评论

My application owners want select text fields to be uppercase as if the caps lock is on. I am using a KnockoutJS viewmodel with observables for these fields. Is there a way I can in effect convert any user entered text to upper case?

I put a input event on the controls I wanted to change but found that although it works, the observables are not updated.

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

I have also been thinking of putting a ucase CSS class on the controls I want to be upper case and then either on the client or server, saving those fields in upper case.

.ucase {
    text-transform: uppercase;
}

My application owners want select text fields to be uppercase as if the caps lock is on. I am using a KnockoutJS viewmodel with observables for these fields. Is there a way I can in effect convert any user entered text to upper case?

I put a input event on the controls I wanted to change but found that although it works, the observables are not updated.

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

I have also been thinking of putting a ucase CSS class on the controls I want to be upper case and then either on the client or server, saving those fields in upper case.

.ucase {
    text-transform: uppercase;
}
Share Improve this question edited Jul 21, 2014 at 17:43 DaveB asked Jul 21, 2014 at 17:24 DaveBDaveB 9,5304 gold badges41 silver badges67 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 11

You could extend your observables -

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

fiddle example - http://jsfiddle/kbFwK/

Basically whenever the value changes it will convert the value of the observable to upper case.

The disadvantage here is that it actually changes the value and would store it that way as well. You could always tack on a puted property onto the observable just for display purposes as well. You could do that using a ko.puted, a custom binding handler (since it is just for presentation), or something similar. If that is more of what you are looking for let me know with a ment.

Edit

Updated with afterkeydown - http://jsfiddle/kbFwK/2/

This is a custom binding I wrote that makes sure both the input field and the observable is upper case. It should work just like a textInput binding.

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

A small caveat. If you write to the observable it will notify other subscribers twice. First when you write to it and then when it gets upper cased.

发布评论

评论列表(0)

  1. 暂无评论