Knockout JS'yi kayıp odak yerine tuşa basıldığında veri bağlama işlevini nasıl alabilirim?


191

Nakavt js örneği, bir alanı düzenleyip SEKME tuşuna bastığınızda, görünüm modeli verileri ve dolayısıyla alanların altındaki metinler güncelleştirildiğinden çalışır.

Viewmodel verilerinin her tuşa basıldığında güncellenmesi için bu kodu nasıl değiştirebilirim?

alternatif metin

<!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'de tüm bu geçici çözümleri yapmaya gerek yok: stackoverflow.com/a/25493265/1090562
Salvador Dali

Salvador doğrudur - en son sürümde otomatik olarak yapar.
vapcguy

Yanıtlar:


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>

Gönderen dokümantasyon

Ek parametreler

  • valueUpdate

    Bağlamanızda valueUpdate adlı bir parametre de varsa, bu, KO'yu değişiklikleri algılamak için hangi tarayıcı olayını kullanması gerektiğini tanımlar. Aşağıdaki dize değerleri en yaygın kullanılan seçimlerdir:

    • "change" (varsayılan) - kullanıcı odağı farklı bir kontrole taşıdığında veya öğeler söz konusu olduğunda, herhangi bir değişiklikten hemen sonra görünüm modelinizi günceller

    • "keyup" - kullanıcı bir anahtar bıraktığında görünüm modelinizi günceller

    • "keypress" - kullanıcı bir anahtar yazdığında görünüm modelinizi günceller. Tuşa basmanın aksine, kullanıcı bir tuşu basılı tutarken bu tekrar tekrar güncellenir

    • "afterkeydown" - kullanıcı bir karakter yazmaya başlar başlamaz görünüm modelinizi günceller. Bu, tarayıcının tuş kilidi etkinliğini yakalayıp etkinliği eşzamansız olarak işleyerek çalışır.

Bu modellerden, görünüm modelinizi gerçek zamanlı olarak güncel tutmak istiyorsanız "afterkeydown" en iyi seçimdir.


9
<eventname> "ifadesinden sonra" sözdizimi "," olaydan sonra işleyiciyi eşzamansız olarak çalıştır "anlamına gelir. Bu, örneğin, tarayıcı denetimi güncelledikten sonra" keydown "olaylarını yakalamak için kullanışlıdır
John Wright

4
Varsayılan olarak valueUpdate: 'afterkeydown' almak için yine de var mı ?
Aaron Shafovaloff

2
bazı giriş kutuları için tarayıcı "otomatik doldurma" değerlerini gösterir (giriş alanına "ad" adı verilmiş gibi). otomatik doldurmadan seçim "afterkeydown" ile çalışmaz. Bunu yakalamanın bir yolu var mı?
Anton

2
@Anton Otomatik doldurma değerlerine ek olarak, yakalanması gereken ekran klavyesi tıklamaları ve fare yapıştırma olayları da vardır. Kullanmak afterkeydownkötü bir çözümdür.
John Kurlak

2
Bu cevabın yazarı, Salvador Dali'nin cevabını da içerecek şekilde güncelleyin, 3.2 olarak eklenen textInput, mobil tarayıcılarla daha iyi uyumluluğa sahip olduğu için daha iyi bir çözümdür (otomatik tamamlama daha iyi işler gibi şeyler)
Michael Crook

85

Gelen sürümü 3.2 basitçe kullanabilirsiniz bağlayıcı TextInput. :

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

İki önemli şey yapar:

  • anında güncelleme yap
  • kesme, sürükleme, otomatik tamamlama için tarayıcı farklılıklarını ...

Bu yüzden ek modüllere, özel kontrollere ve diğer şeylere gerek yok.


Bu gerçekten iyi çalışıyor ve tam olarak değeri değiştirmek için gereken şey: field, valueUpdate: 'giriş değişikliği' benim app aracılığıyla vardı ... :) teşekkürler.
Tod Thomson

Kullanıcı yeni HTML5 arama giriş alanındaki 'x' simgesini tıkladığında ve girişin boş olması durumunda olduğu gibi davrandığında etkinliği yakalamanın bir yolu var mı?
Codrina Valo

35

afterkeydown"Varsayılan olarak " üzerinde güncellemeler yapmasını istiyorsanız valueUpdate, valuebağlayıcı işleyicisine bağlamayı enjekte edebilirsiniz . Sadece allBindingsAccessorişleyicinin kullanması için yeni bir malzeme sağlayın 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
    };
} ());

Bağlamayı "geçersiz kılma" konusunda rahat valuedeğilseniz, geçersiz kılma özel bağlayıcısına farklı bir ad verebilir ve bu bağlayıcı işleyicisini kullanabilirsiniz.

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

gösteri

Bunun gibi bir çözüm Knockout sürüm 2.x için uygun olacaktır. Nakavt ekibi, Nakavt sürüm 3 ve sonraki sürümlerde textInput ciltleme yoluyla metin benzeri girdiler için daha eksiksiz bir ciltleme gerçekleştirdi . Metin girişleri ve için tüm metin giriş yöntemlerini işlemek üzere tasarlanmıştır textarea. Hatta bu yaklaşımı etkin bir şekilde geçersiz kılan gerçek zamanlı güncellemeyi bile ele alacaktır.


2
Bu şekilde işaretlememi biraz daha düzenli hale getiriyorum. Ayrıca, 'afterkeydown' öğesine ek olarak, yapıştırma / sürükleme ve bırakma eylemlerini işlemek için 'giriş' ve 'yapıştırma' olayları eklenebilir.
bob

Yukarıdaki çözümde "typeof valueUpdated === 'array'" yerine "Object.prototype.toString.call (valueUpdate) === '[object Array]'" kullanılması gerektiğini düşünüyorum. Bkz. Stackoverflow.com/questions/4775722/…
daveywc

20

Jeff Mercado'nun cevabı harika, ama ne yazık ki Nakavt 3 ile kırıldı.

Ama Knockout 3 değişiklikleri üzerinde çalışırken ko devs tarafından önerilen cevabı buldum. Aşağıdaki yorumlara https://github.com/knockout/knockout/pull/932 adresinden bakın . Kodları:

//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 artık yeni "textInput" bağlaması ile daha eksiksiz bir çözüme sahip. SalvidorDali'nin cevabına bakın


1
Cevabı 3.0'a güncellediğiniz için teşekkür ederiz!
Graham T

@GrahamT KO 3.2'de ihtiyacınız bile yok. Öyle sadece bir satır
Salvador Dali

Başladığımızda TextInput'u bilmeyen ve tüm sistemdeki her girdiyi güncelleyemeyen KO 3.2'de çok güzeliz!
cscott530
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.