Soru Nakavt ciltleme ile seçili olayı değiştir, gerçek bir değişiklik olup olmadığını nasıl anlarım?


Bir izinler kullanıcı arayüzü yapıyorum, her bir iznin yanında bir seçim listesiyle izinler listesi var. İzinler, bir seçim listesine bağlı olan gözlenebilir bir nesne dizisiyle temsil edilir:

<div data-bind="foreach: permissions">
     <div class="permission_row">
          <span data-bind="text: name"></span>
          <select data-bind="value: level, event:{ change: $parent.permissionChanged}">
                   <option value="0"></option>
                   <option value="1">R</option>
                   <option value="2">RW</option>
           </select>
      </div>
 </div>

Şimdi sorun şudur: UI sadece ilk kez doldurulduğunda değişiklik olayı yükselir. Ajax işlevimi çağırıyorum, izinler listesini al ve sonra izin öğelerinin her biri için olay yükseltiliyor. Bu gerçekten istediğim davranış değil. Yükseltilmesini istiyorum yalnızca bir kullanıcı seçim listesindeki izin için yeni bir değer seçtiğinde, bunu nasıl yapabilirim?


72
2018-06-18 06:42


Menşei




Cevaplar:


Aslında Etkinliğin kullanıcı veya program tarafından tetiklenip tetiklenmediğini öğrenmek istediğinizde ve bu olayın, başlatma sırasında tetikleneceği açıktır.

Ekleme nakavt yaklaşımı subscription Her durumda yardımcı olmayacaktır, çünkü neden çoğu modelde bunun gibi uygulanacak?

  1. tanımlanmamış veri ile model init, sadece yapı (actual KO initilization)
  2. modeli ilk verilerle güncelleyin (logical init like load JSON , get data etc)
  3. Kullanıcı etkileşimi ve güncellemeleri

Yakalamak istediğimiz asıl adım 3'teki değişiklikler, ancak ikinci adımda subscription çağrı alacak Yani, daha iyi bir yol,

 <select data-bind="value: level, event:{ change: $parent.permissionChanged}">

ve olay tespit edildi permissionChanged fonksiyon

this.permissionChanged = function (obj, event) {

  if (event.originalEvent) { //user changed

  } else { // program changed

  }

}

77
2017-12-05 10:35



Bunun doğru cevap olarak işaretlenmesi gerektiğini düşünüyorum. Soruda açıklandığı gibi tam senaryoyu aldım ve dizeleri geçen anahtar olarak test ettim. select öğesi. Bununla birlikte, seçimin başlangıç ​​değeri seçeneklerden birine eşleştiğinde bile, yine de tetiklenir. change Etkinlik. Bu basit uygulandığında if işleyicide blok, her şey beklendiği gibi çalıştı. İlk önce bu yöntemi deneyin. Teşekkürler, @Saat! - Pflugs
Kullanıcı değişti ve program değişti arasında ayrım yapma kavramını seviyorum. Bu, günlük durumlarda, özellikle de gözlemlenebilirlerin, herhangi bir kullanıcı etkileşimi olmadan değeri değiştirmenin mümkün olduğu nakavt ile yardımcı olur. - Rodiwa
Benim için çalışılan etkinlik türleri arasında ayrım yaparak, @Pflugs ile katılıyorum ve bu kabul edilen cevap olmalıdır. - Emma Middlebrook
def kabul edilmiş bir cevap olmalıdır ... event type özelliği, prissionChanged'in tetiklenmesini ayırt etmek için kullanılabilir - caniaskyouaquestion
Ayrıca, kullanıcının başka bir tetikleyici yerine bir seçim değiştirip değiştirmediğini saptamak için bu yöntemi kullandı. Benim durumumda, "seçenekler" bağlaması yoluyla seçenekler değerlerini güncellemek, "değişiklik" olayını tetikledi. - nath


Bu sadece bir tahmin, ama bence oluyor çünkü level bir sayıdır. Bu durumda value bağlama bir tetikleyecek change güncellenecek etkinlik level dize değeri ile. Bu nedenle, bunu düzeltebilirsiniz. level ile başlayan bir dizedir.

Ek olarak, bunu yapmanın daha "nakavt" yolu, olay işleyicilerini kullanmamak, ancak gözlenebilirleri ve abonelikleri kullanmaktır. Yapmak level bir gözlemlenebilir ve daha sonra, her ne zaman yayınlanacak bir abonelik ekleyin level değişir.


32
2018-06-20 01:51



2 saatlik kazma sonrasında, sayfam yüklendikten sonra 'değişiklik' olayını tetikleyen formum beni tahmin etti. - Samih A
Cevabınız bana bir fikir verdi ... Ben url gelen türünü bilerek değiştirdim, bu yüzden benim abone fonksiyonu (sayfa benim açılan bir değişiklik tetiklediğinde değil, bir url var işlemek istedim) sayfa yükü üzerinde tetikleyecektir. Bunu yapmanın daha az zor bir yolu var mı? - Jiffy


İşte bu garip davranışa yardımcı olabilecek bir çözüm. Değişiklik olayını manuel olarak tetiklemek için bir düğmeden daha iyi bir çözüm bulamadım.

DÜZENLEME: Belki de bu gibi özel bir bağlanma yardımcı olabilir:

ko.bindingHandlers.changeSelectValue = {

   init: function(element,valueAccessor){

        $(element).change(function(){

            var value = $(element).val();

            if($(element).is(":focus")){

                  //Do whatever you want with the new value
            }

        });

    }
  };

Ve select data-bind özniteliğinde şunu ekleyin:

changeSelectValue: yourSelectValue

4
2018-06-18 09:04



oh ... kaydet düğmesi gibi mi demek istiyorsun? .. benim için iyi değil .. gerçekten çalışmak için buna ihtiyacım var :) - guy schaller
Cevabı daha iyi bir çözümle değiştirin (umarım). - Ingro
Hey Ingro, bu bir cevap olarak (yanlış) işaretlendi. İlk cümlenin reword'unu yaptım, bu yüzden flagger'lar yanlışlıkla bir soru olarak cevaplandırdığınızı düşünmezler. Bu yardımcı olur umarım! :) - jmort253
@ jmort253: Üzgünüm, bu benim hatamdı. Başka bir şey soruyormuş gibi gözüktüğü için, "Bende de aynı problemim var" ifadesini kullanmamanın daha iyi olur. Bunun yerine, bir cevaba doğrudan bir çözüm sunun ve nasıl çalıştığını açıklayın. - Qantas 94 Heavy
Evet üzgünüm, benim hatam. Stackoverflow'ta yayınladığım ilk cevaplardan biriydi ve tüm kuralları bilmiyordum. Düzenleme için teşekkürler! - Ingro


Bu özel bağlama kullanıyorum bu RP Niemeyer tarafından keman, onun cevabını görmek bu soru), sayısal değerin diziden sayıya doğru şekilde dönüştürülmesini sağlar (Michael Best çözümünün önerdiği gibi):

JavaScript:

ko.bindingHandlers.valueAsNumber = {
    init: function (element, valueAccessor, allBindingsAccessor) {
        var observable = valueAccessor(),
            interceptor = ko.computed({
                read: function () {
                    var val = ko.utils.unwrapObservable(observable);
                    return (observable() ? observable().toString() : observable());
                },
                write: function (newValue) {
                    observable(newValue ? parseInt(newValue, 10) : newValue);
                },
                owner: this
            });
        ko.applyBindingsToNode(element, { value: interceptor });
    }
};

Örnek HTML:

<select data-bind="valueAsNumber: level, event:{ change: $parent.permissionChanged }">
    <option value="0"></option>
    <option value="1">R</option>
    <option value="2">RW</option>
</select>

3
2018-06-13 10:12





İlkel bir değer yerine gözlemlenebilir kullanırsanız, seçim ilk ciltlemede değişiklik olaylarını yükseltmez. Doğrudan gözlemlenebilir aboneye abone olmak yerine değişiklik etkinliğine bağlanmaya devam edebilirsiniz.


2
2018-01-25 17:51





Hızlı ve kirli, basit bir bayrak kullanarak:

var bindingsApplied = false;

var ViewModel = function() {
    // ...

    this.permissionChanged = function() {
        // ignore, if flag not set
        if (!flag) return;

        // ...
    };
};

ko.applyBindings(new ViewModel());
bindingsApplied = true; // done with the initial population, set flag to true

Bu işe yaramazsa, setTimeout () içindeki son satırı sarmalamayı deneyin () - olaylar eşzamansızdır, bu yüzden applyBindings () zaten geri döndüğünde belki sonuncu hala beklemede kalır.


1
2018-06-18 07:11



merhaba cevabı için teşekkürler, bu benim için işe yaramaz çünkü dom hazır olduğunda ko.applyBindings'i çağırıyorum, ancak izinlerim daha sonraki bir aşamada benim modelime dolduruluyor ... bu yüzden bayrak doğru olurdu ama sorun yine de olurdu. - guy schaller


Benzer bir sorun yaşadım ve yalnızca değişkenini kontrol etmek için olay işleyicisini değiştirdim. Tür, yalnızca sayfa ilk yüklendiğinde değil, kullanıcı bir değer seçtikten sonra ayarlanır.

self.permissionChanged = function (l) {
    if (typeof l != 'undefined') {
        ...
    }
}

Bu benim için çalışıyor gibi görünüyor.


0
2018-05-30 15:41





Knockout kullanarak çalışıyorsanız, gözlemlenebilir işlevselliğin devre dışı bırakılması işlevini kullanın.
kullanım ko.computed() metodu ve ajax çağrısını bu fonksiyon içerisinde gerçekleştirir.


0
2018-04-26 13:35