jQuery - Gizli giriş alanındaki değer değişikliğini algıla


270

Ben bir AJAX yanıtı ile güncellenen gizli bir metin alanı var.

<input type="hidden" value="" name="userid" id="useid" />

Bu değer değiştiğinde bir AJAX isteği başlatmak istiyorum. Herkes değişikliği nasıl tespit edeceğiniz konusunda tavsiyede bulunabilir mi?

Aşağıdaki kodu var, ama nasıl değer aramak için bilmiyorum:

$('#userid').change( function() {  
    alert('Change!'); 
}) 

2
Bir ajax yanıtı ile güncellenirse, neden yanıtın başarı işlevinde yeni ajax isteğini başlatmıyorsunuz?
BonyT

2
$ ('# userid'). val () istediğin buysa değeri verecektir
BonyT

GÜNCELLEME: artık gizli bir alanın değeri güncellendiğinde bir değişiklik olayı tetiklenir.
Steven

Yanıtlar:


622

Yani bu çok geç, ama ben bu konuya gelen herkes için yararlı olur diye bir cevap keşfettim.

Gizli öğelerde değer değişiklikleri, .change () olayını otomatik olarak tetiklemez. Bu nedenle, bu değeri ayarladığınız her yerde, jQuery'ye bunu tetiklemesini de söylemeniz gerekir.

function setUserID(myValue) {
     $('#userid').val(myValue)
                 .trigger('change');
}

Bir kez böyle,

$('#userid').change(function(){
      //fire your ajax call  
})

beklendiği gibi çalışmalıdır.


5
.trigger()Genellikle sadece aramada kullanmak daha mı iyidir change()?
Hanna

1
Çalışıyor, ancak değişiklik olayını iki kez tetikliyor gibi görünüyor !. Eğer bu kodu koyarsanız, iki kez treggers, eğer kodu kaldırırsanız, hiçbir tetikleyici w / e. !!
Janx from Venezuela

1
changeOlayla aynı şekilde davranması için setUserID(), değerin gerçekten değişip değişmediğini kontrol etmek için kodu eklemeniz gerekir . if ($('#userid').val() != myVaule) { // set val() and trigger change }
nnattawat

1
Eğer javascript aracılığıyla değiştirilmesini olarak, aksi javascript tarafından yapılan değişiklikler .change (işleyici) ya da .sistem ( "değişim", işleyici) tarafından yakalanmış olamaz bir "değişim" olayı yakalamak için çalışıyoruz, bu özellikle yararlıdır
JJK

7
Bu yüzden gizli alanın değerini değiştiren işlev üzerinde kontrolüm yoksa (yani tetikleyiciyi ateşleyemez), bu çözüm işe yaramaz, değil mi?
osama yaccoub

31

Gizli girdi değişiklik "değişiklik" olayını tetiklemediğinden, bunun yerine bunu tetiklemek için MutationObserver kullandım.

(Bazen gizli giriş değeri değişiklikleri, değiştiremeyeceğiniz diğer komut dosyaları tarafından yapılır)

Bu IE10 ve altında çalışmaz

MutationObserver = window.MutationObserver || window.WebKitMutationObserver;

var trackChange = function(element) {
  var observer = new MutationObserver(function(mutations, observer) {
    if(mutations[0].attributeName == "value") {
        $(element).trigger("change");
    }
  });
  observer.observe(element, {
    attributes: true
  });
}

// Just pass an element to the function to start tracking
trackChange( $("input[name=foo]")[0] );

AFAIK mutationobserver da (gizli eğer olursa olsun ya da olmasın) bir metin alanını bir değişikliği kovulacağım ETMEZ
Ole Albers

3
Harika çalışıyor! @OleAlbers - OP hakkında sorduinput[type=hidden]
Shay

1
Bu gizli giriş alanı değerleri bir koleksiyon almak için jquery map komutunu kullanarak bir işlevle birlikte kullandım. Çok teşekkürler @lulalala!
AdamJones

2
Basit ve kolay anlaşılır. "Değeri değiştirdiğinizde olayı tetiklemelisiniz" çözümlerinin aksine, bu çözüm, değerin değiştirildiği noktada koda erişimi olan programcıya güvenmez; IE11'den daha eski bir sürümü desteklemesi gerekmez. Çok işime yaradı. Teşekkürler
Joe Salazar

Harika bir çözüm! Teşekkür ederim! Bazı nedenlerden dolayı trigger('change')benim için çalışmadı, bu yüzden bir CustomEvent oluşturdum, kaydettirdim ve sonraelement.dispatchEvent(myCustomEvent)
tbutcaru

8

Aşağıdaki işlevi basitçe kullanabilirsiniz, Yazım elemanını da değiştirebilirsiniz.

 $("input[type=hidden]").bind("change", function() {
       alert($(this).val()); 
 });

Gizli öğelerde değer değişiklikleri, .change () olayını otomatik olarak tetiklemez. Bu nedenle, bu değeri ayarladığınız her yerde, jQuery'ye bunu tetiklemesini de söylemeniz gerekir.

HTML

 <div id="message"></div>
<input type="hidden" id="testChange" value="0"  />    

JAVASCRIPT

var $message = $('#message');
var $testChange = $('#testChange');
var i = 1;

function updateChange() {
    $message.html($message.html() + '<p>Changed to ' + $testChange.val() + '</p>');
}

$testChange.on('change', updateChange);

setInterval(function() {
    $testChange.val(++i).trigger('change');; 
    console.log("value changed" +$testChange.val());
}, 3000);

updateChange();

beklendiği gibi çalışmalıdır.

http://jsfiddle.net/7CM6k/3/


1
Benim için çalışmıyor ... Her neyse, değeri bir Gizli Alana yapıştırmak nasıl mümkün olabilir? : /
Simon Dugré

Hey Teşekkürler, macun orada olmamalı, ancak değişiklik gizli alan değişikliği olayını algılayabilir
Tarun Gupta

@KrisErickson Keman için teşekkürler, kodu açıkça algılayabilmesi için kodu güncelledim, lütfen güncellenen kemanı takip edin jsfiddle.net/7CM6k/3
Tarun Gupta

1
@TarunGupta evet tetik üzerinde çalışıyor, ancak değeri değiştirmiyor. Bir gizli değeri değiştiğinde tarayıcılar change olayını tetiklemez, manuel olarak yapmanız gerekir.
Kris Erickson

Tüm gizli alanlara bağlanma ile ilgili bu cevabın ilk kısmı çok yardımcı oldu. Teşekkürler!
Çad

6
$('#userid').change(function(){
  //fire your ajax call  
});

$('#userid').val(10).change();

4

Object.defineProperty()Giriş öğesinin 'value' özelliğini yeniden tanımlamak ve değiştirme sırasında herhangi bir şey yapmak için kullanmak mümkündür .

Object.defineProperty() bir mülk için bir alıcı ve ayarlayıcı tanımlamamıza izin verir, böylece onu kontrol eder.

replaceWithWrapper($("#hid1")[0], "value", function(obj, property, value) { 
  console.log("new value:", value)
});

function replaceWithWrapper(obj, property, callback) {
  Object.defineProperty(obj, property, new function() {
    var _value = obj[property];
    return {
      set: function(value) {
        _value = value;
        callback(obj, property, value)
      },
      get: function() {
        return _value;
      }
    }
  });
}

$("#hid1").val(4);

https://jsfiddle.net/bvvmhvfk/


1
Bu yaklaşımı seviyorum, özellikle de herkesin cevabı "değişikliği kendiniz tetikleyin" ... çünkü bu her zaman mümkün değildir.
sMyles

1
bu neredeyse benim için çalışıyor, gizli alandaki son değer hariç her şey aslında değişmiyor, jsfiddle'ı kontrol ederseniz gizli alan değeri '123'den (Chrome kullanarak)
değişmez

Çok yakın, ancak diğerlerinin de belirttiği gibi, alan için orijinal mutasyona / ayarlayıcıya bir referans sağlamaz, bu nedenle güncellemeler gizli girdinin kendisini etkilemez. Bu yaklaşımın ve bu yaklaşımın parçalarını içeren yeni bir çözüm
gönderiyorum

0

Bu örnek, gizli taslak alanın değerini her değiştirdiğinde taslak alan değerini döndürür (krom tarayıcı):

var h = document.querySelectorAll('input[type="hidden"][name="draft"]')[0];
//or jquery.....
//var h = $('input[type="hidden"][name="draft"]')[0];

observeDOM(h, 'n', function(draftValue){ 
  console.log('dom changed draftValue:'+draftValue);
});


var observeDOM = (function(){
var MutationObserver = window.MutationObserver || 
window.WebKitMutationObserver;

  return function(obj, thistime, callback){
    if(typeof obj === 'undefined'){
      console.log('obj is undefined');
      return;
    }

    if( MutationObserver ){

        // define a new observer
        var obs = new MutationObserver(function(mutations, observer){

            if( mutations[0].addedNodes.length || mutations[0].removedNodes.length ){

               callback('pass other observations back...');

            }else if(mutations[0].attributeName == "value" ){

               // use callback to pass back value of hidden form field                            
               callback( obj.value );

            }

        });

        // have the observer observe obj for changes in children
        // note 'attributes:true' else we can't read the input attribute value
        obs.observe( obj, { childList:true, subtree:true, attributes:true  });

       }
  };
})();

0

Viktar'ın cevabından yola çıkarak, giriş öğesinin değeri her değiştiğinde sonraki değişiklik olayının tetiklenmesini sağlamak için belirli bir gizli giriş öğesinde bir kez çağırabileceğiniz bir uygulama:

/**
 * Modifies the provided hidden input so value changes to trigger events.
 *
 * After this method is called, any changes to the 'value' property of the
 * specified input will trigger a 'change' event, just like would happen
 * if the input was a text field.
 *
 * As explained in the following SO post, hidden inputs don't normally
 * trigger on-change events because the 'blur' event is responsible for
 * triggering a change event, and hidden inputs aren't focusable by virtue
 * of being hidden elements:
 * https://stackoverflow.com/a/17695525/4342230
 *
 * @param {HTMLInputElement} inputElement
 *   The DOM element for the hidden input element.
 */
function setupHiddenInputChangeListener(inputElement) {
  const propertyName = 'value';

  const {get: originalGetter, set: originalSetter} =
    findPropertyDescriptor(inputElement, propertyName);

  // We wrap this in a function factory to bind the getter and setter values
  // so later callbacks refer to the correct object, in case we use this
  // method on more than one hidden input element.
  const newPropertyDescriptor = ((_originalGetter, _originalSetter) => {
    return {
      set: function(value) {
        const currentValue = originalGetter.call(inputElement);

        // Delegate the call to the original property setter
        _originalSetter.call(inputElement, value);

        // Only fire change if the value actually changed.
        if (currentValue !== value) {
          inputElement.dispatchEvent(new Event('change'));
        }
      },

      get: function() {
        // Delegate the call to the original property getter
        return _originalGetter.call(inputElement);
      }
    }
  })(originalGetter, originalSetter);

  Object.defineProperty(inputElement, propertyName, newPropertyDescriptor);
};

/**
 * Search the inheritance tree of an object for a property descriptor.
 *
 * The property descriptor defined nearest in the inheritance hierarchy to
 * the class of the given object is returned first.
 *
 * Credit for this approach:
 * https://stackoverflow.com/a/38802602/4342230
 *
 * @param {Object} object
 * @param {String} propertyName
 *   The name of the property for which a descriptor is desired.
 *
 * @returns {PropertyDescriptor, null}
 */
function findPropertyDescriptor(object, propertyName) {
  if (object === null) {
    return null;
  }

  if (object.hasOwnProperty(propertyName)) {
    return Object.getOwnPropertyDescriptor(object, propertyName);
  }
  else {
    const parentClass = Object.getPrototypeOf(object);

    return findPropertyDescriptor(parentClass, propertyName);
  }
}

Bu belgeye şu şekilde hazır olarak çağırın:

$(document).ready(function() {
  setupHiddenInputChangeListener($('myinput')[0]);
});

-4

Bu konu 3 yaşında olmasına rağmen, işte benim çözümüm:

$(function ()
{
    keep_fields_uptodate();
});

function keep_fields_uptodate()
{
    // Keep all fields up to date!
    var $inputDate = $("input[type='date']");
    $inputDate.blur(function(event)
    {
        $("input").trigger("change");
    });
}

3
bulanıklık olayı yalnızca giriş odağı kaybettiğinde tetiklenir. Gizli bir giriş için geçerli bir yanıt değil
manuerumx
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.