잃어버린 초점 대신 키 누르기를 사용하여 녹아웃 JS를 데이터 바인딩 할 수 있습니까?


191

녹아웃 js 예제는 필드를 편집하고 Tab 키를 누르면 뷰 모델 데이터와 필드 아래의 텍스트가 업데이트되므로 작동합니다.

키를 누를 때마다 뷰 모델 데이터가 업데이트되도록이 코드를 어떻게 변경합니까?

대체 텍스트

<!doctype html>
<html>
    <title>knockout js</title>
    <head>
        <script type="text/javascript" src="js/knockout-1.1.1.debug.js"></script>
        <script type="text/javascript">
        window.onload= function() {

            var viewModel = {
                firstName : ko.observable("Jim"),
                lastName : ko.observable("Smith")
            };
            viewModel.fullName = ko.dependentObservable(function () {
                return viewModel.firstName() + " " + viewModel.lastName();
            });

            ko.applyBindings(viewModel);
       }
        </script>
    </head>
    <body>
        <p>First name: <input data-bind="value: firstName" /></p>
        <p>Last name: <input data-bind="value: lastName" /></p>
        <h2>Hello, <span data-bind="text: fullName"> </span>!</h2>
    </body>
</html>

9
: KO 3.2이 모든 해결 방법을 수행 할 필요가 없습니다에 stackoverflow.com/a/25493265/1090562
살바도르 달리

살바도르는 정확합니다-최신 버전에서 자동으로 수행됩니다.
vapcguy

답변:


299
<body>
        <p>First name: <input data-bind="value: firstName, valueUpdate: 'afterkeydown'" /></p>
        <p>Last name: <input data-bind="value: lastName, valueUpdate: 'afterkeydown'" /></p>
        <h2>Hello, <span data-bind="text: fullName"> </span>!</h2>
</body>

로부터 문서

추가 매개 변수

  • valueUpdate

    바인딩에 valueUpdate라는 매개 변수도 포함되어 있으면 변경을 감지하기 위해 KO를 사용해야하는 브라우저 이벤트가 정의됩니다. 다음 문자열 값이 가장 일반적으로 유용한 선택입니다.

    • "change"(기본값)-사용자가 변경 후 즉시 다른 컨트롤 또는 요소의 경우 포커스를 이동하면 뷰 모델이 업데이트됩니다.

    • "키업"-사용자가 키를 놓을 때 뷰 모델을 업데이트합니다

    • "keypress"-사용자가 키를 입력하면 뷰 모델이 업데이트됩니다. 키 업과 달리이 키는 사용자가 키를 누른 상태에서 반복적으로 업데이트됩니다.

    • "afterkeydown"-사용자가 문자 입력을 시작하자마자 뷰 모델을 업데이트합니다. 이것은 브라우저의 키 다운 이벤트를 포착하고 이벤트를 비동기 적으로 처리하여 작동합니다.

이러한 옵션 중에서 뷰 모델을 실시간으로 업데이트하려면 "afterkeydown"이 최선의 선택입니다.


9
knockout.js의 문서에서 : // "after <eventname>"구문은 "이벤트 후에 비동기 적으로 핸들러 실행"을 의미합니다. // 예를 들어 브라우저가 컨트롤을 업데이트 한 후 "키 다운"이벤트를 잡는 데 유용
John Wright

4
어쨌든 valueUpdate : 'afterkeydown'을 기본값으로 사용 합니까?
Aaron Shafovaloff

2
일부 입력 상자의 경우 브라우저에 "자동 입력"값이 표시됩니다 (예 : 입력 필드의 이름이 "firstname"인 경우). 자동 입력에서 선택하면 "afterkeydown"에서 작동하지 않습니다. 이것을 잡을 방법이 있습니까?
Anton

2
@Anton 값을 자동으로 채우는 것 외에도 화면 키보드 클릭과 마우스 붙여 넣기 이벤트도 있습니다. 사용 afterkeydown하는 것은 나쁜 해결책입니다.
John Kurlak

2
이 답변을 작성한 사람은 Salvador Dali의 답변도 포함하도록 업데이트하십시오. 3.2 이상으로 추가 된 textInput은 모바일 브라우저와의 호환성이 향상되어 더 나은 솔루션입니다 (자동 완성과 같은 기능)
Michael Crook

85

버전 3.2 에서는 단순히 텍스트 입력 바인딩을 사용할 수 있습니다 . :

<input data-bind="textInput: userName" />

두 가지 중요한 일을합니다.

  • 즉시 업데이트
  • 잘라 내기, 끌기, 자동 완성에 대한 브라우저 차이점을 처리합니다 ...

따라서 추가 모듈, 사용자 정의 컨트롤 및 기타 사항이 필요하지 않습니다.


이것은 정말 잘 작동하고 정확하게 value : field, valueUpdate : '내 입력 변경'을 통해 모든 앱을 통해 얻은 것입니다. :) 감사합니다.
토드 톰슨

사용자가 새로운 HTML5 검색 입력 필드에서 'x'아이콘을 클릭하고 입력이 비어있는 경우처럼 동작 할 때 이벤트를 캡처하는 방법이 있습니까?
Codrina Valo

35

afterkeydown"기본적 으로 " 업데이트를 valueUpdate하려면 value바인딩 핸들러에 바인딩을 삽입하면 됩니다. allBindingsAccessor처리기가 사용할 새 항목 을 제공하면 됩니다 afterkeydown.

(function () {
    var valueHandler = ko.bindingHandlers.value;
    var getInjectValueUpdate = function (allBindingsAccessor) {
        var AFTERKEYDOWN = 'afterkeydown';
        return function () {
            var allBindings = ko.utils.extend({}, allBindingsAccessor()),
                valueUpdate = allBindings.valueUpdate;

            if (valueUpdate === undefined) {
                return ko.utils.extend(allBindings, { valueUpdate: AFTERKEYDOWN });
            } else if (typeof valueUpdate === 'string' && valueUpdate !== AFTERKEYDOWN) {
                return ko.utils.extend(allBindings, { valueUpdate: [valueUpdate, AFTERKEYDOWN] });
            } else if (typeof valueUpdate === 'array' && ko.utils.arrayIndexOf(valueUpdate, AFTERKEYDOWN) === -1) {
                valueUpdate = ko.utils.arrayPushAll([AFTERKEYDOWN], valueUpdate);
                return ko.utils.extend(allBindings, {valueUpdate: valueUpdate});
            }
            return allBindings;
        };
    };
    ko.bindingHandlers.value = {
        // only needed for init
        'init': function (element, valueAccessor, allBindingsAccessor) {
            allBindingsAccessor = getInjectValueUpdate(allBindingsAccessor);
            return valueHandler.init(element, valueAccessor, allBindingsAccessor);
        },
        'update': valueHandler.update
    };
} ());

value바인딩을 "재정의"하는 것이 불편한 경우 재정의하는 사용자 정의 바인딩에 다른 이름을 지정하고 해당 바인딩 핸들러를 사용할 수 있습니다.

ko.bindingHandlers.realtimeValue = { 'init':..., 'update':... };

데모

이와 같은 솔루션은 Knockout 버전 2.x에 적합합니다. Knockout 팀은 Knockout 버전 3 이상의 textInput 바인딩을 통해 텍스트와 유사한 입력에 대한보다 완벽한 바인딩을 구현 했습니다. 텍스트 입력 및에 대한 모든 텍스트 입력 방법을 처리하도록 설계되었습니다 textarea. 실시간 업데이트도 처리하여이 접근 방식을 효과적으로 폐기합니다.


2
이렇게하면 내 마크 업이 좀 더 깔끔해집니다. 또한 'afterkeydown'외에도 'input'및 'paste'이벤트를 추가하여 붙여 넣기 / 드래그 앤 드롭 작업을 처리 할 수 ​​있습니다.
bob

위의 솔루션에서 "typeof valueUpdated === 'array'"를 "Object.prototype.toString.call (valueUpdate) === '[object Array]'"로 바꿔야한다고 생각합니다. 참조 stackoverflow.com/questions/4775722/...
daveywc

20

Jeff Mercado의 답변은 환상적이지만 불행히도 Knockout 3에서 깨졌습니다.

그러나 Knockout 3 변경을 통해 작업하면서 ko 개발자가 제안한 답변을 찾았습니다. https://github.com/knockout/knockout/pull/932 에서 하단 주석을 참조하십시오 . 그들의 코드 :

//automatically add valueUpdate="afterkeydown" on every value binding
(function () {
    var getInjectValueUpdate = function (allBindings) {
        return {
            has: function (bindingKey) {
                return (bindingKey == 'valueUpdate') || allBindings.has(bindingKey);
            },
            get: function (bindingKey) {
                var binding = allBindings.get(bindingKey);
                if (bindingKey == 'valueUpdate') {
                    binding = binding ? [].concat(binding, 'afterkeydown') : 'afterkeydown';
                }
                return binding;
            }
        };
    };

    var valueInitHandler = ko.bindingHandlers.value.init;
    ko.bindingHandlers.value.init = function (element, valueAccessor, allBindings, viewModel, bindingContext) {
        return valueInitHandler(element, valueAccessor, getInjectValueUpdate(allBindings), viewModel, bindingContext);
    };
}());

http://jsfiddle.net/mbest/GKJnt/

Edit Ko 3.2.0은 이제 새로운 "textInput"바인딩을 통해보다 완벽한 솔루션을 제공합니다. SalvidorDali의 답변보기


1
답변을 3.0으로 업데이트 해 주셔서 감사합니다!
Graham T

KO 3.2의 @GrahamT는 필요하지 않습니다. 그것은 단지 한 줄입니다
Salvador Dali

우리가 시작할 때 TextInput에 대해 몰랐고 전체 시스템의 모든 입력을 업데이트 할 수없는 KO 3.2 사용자에게는 매우 좋습니다!
cscott530
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.