jQuery - Wertänderung im ausgeblendeten Eingabefeld erkennen

270

Ich habe ein verstecktes Textfeld, dessen Wert über eine AJAX-Antwort aktualisiert wird.

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

Wenn sich dieser Wert ändert, möchte ich eine AJAX-Anfrage auslösen. Kann jemand raten, wie man die Änderung erkennt?

Ich habe den folgenden Code, weiß aber nicht, wie ich nach dem Wert suchen soll:

$('#userid').change( function() {  
    alert('Change!'); 
}) 
Ben
quelle
2
Wenn es über eine Ajax-Antwort aktualisiert wird, warum lösen Sie dann nicht einfach die neue Ajax-Anforderung in der Erfolgsfunktion der Antwort aus?
BonyT
2
$ ('# userid'). val () gibt Ihnen den Wert, wenn Sie danach fragen
BonyT
UPDATE: Ein Änderungsereignis wird jetzt ausgelöst, wenn der Wert eines ausgeblendeten Feldes aktualisiert wird.
Steven

Antworten:

622

Das ist also viel spät, aber ich habe eine Antwort gefunden, falls sie für jemanden nützlich sein sollte, der auf diesen Thread stößt.

Wertänderungen an ausgeblendeten Elementen lösen das Ereignis .change () nicht automatisch aus. Wo immer Sie diesen Wert festlegen, müssen Sie jQuery auch anweisen, ihn auszulösen.

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

Sobald dies der Fall ist,

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

sollte wie erwartet funktionieren.

Yycroman
quelle
5
Ist es im .trigger()Allgemeinen besser, nur zu telefonieren change()?
Hanna
1
Es funktioniert, aber es scheint, als würde es das Änderungsereignis zweimal auslösen!. Ist wie wenn ich diesen Code setze, wird er zweimal ausgelöst, wenn ich den Code entferne, keine Auslöser w / e. !!
Janx aus Venezuela
1
Damit es sich wie ein changeEreignis verhält , sollten Sie den Code hinzufügen setUserID(), um zu überprüfen, ob sich der Wert wirklich ändert oder nicht. if ($('#userid').val() != myVaule) { // set val() and trigger change }
Nnattawat
1
Dies ist besonders nützlich , wenn Sie versuchen , ein „Änderung“ Ereignis zu fangen , dass als über Javascript geändert werden, da sonst die von Javascript vorgenommenen Änderungen nicht durch den .change (Handler) oder .on ( „change“, handler) gefangen werden
JJK
7
Wenn ich also keine Kontrolle über die Funktion habe, die den Wert des ausgeblendeten Felds ändert (dh den Trigger nicht auslösen kann), funktioniert diese Lösung nicht, oder?
Osama Yaccoub
31

Da versteckte Eingaben bei Änderungen kein "Änderungs" -Ereignis auslösen, habe ich stattdessen MutationObserver verwendet, um dies auszulösen.

(Manchmal werden versteckte Eingabewertänderungen von anderen Skripten vorgenommen, die Sie nicht ändern können.)

Dies funktioniert nicht in IE10 und darunter

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] );
lulalala
quelle
AFAIK der Mutationsbeobachter wird auch NICHT auf eine Änderung in einem Textfeld gefeuert (egal ob versteckt oder nicht)
Ole Albers
3
Funktioniert super! @OleAlbers - OP fragte nachinput[type=hidden]
Shay
1
Ich habe dies in Kombination mit einer Funktion verwendet, die den Befehl map von jquery verwendete, um eine Sammlung versteckter Eingabefeldwerte abzurufen. Vielen Dank @lulalala!
AdamJones
2
Einfach und leicht zu verstehen. Diese Lösung setzt im Gegensatz zu den Lösungen "Sie müssen das Ereignis auslösen, wenn Sie den Wert ändern" nicht voraus, dass der Programmierer an dem Punkt, an dem der Wert geändert wird, Zugriff auf den Code hat. Dies macht ihn nützlicher, solange Sie ihn nicht verwenden Es muss keine ältere Version als IE11 unterstützt werden. Es hat super für mich funktioniert. Vielen Dank
Joe Salazar
Tolle Lösung! Danke dir! Aus irgendeinem Grund hat das trigger('change')bei mir nicht funktioniert, also habe ich ein CustomEvent erstellt, es registriert und dannelement.dispatchEvent(myCustomEvent)
tbutcaru
8

Sie können einfach die folgende Funktion verwenden. Sie können auch das Typelement ändern.

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

Wertänderungen an ausgeblendeten Elementen lösen das Ereignis .change () nicht automatisch aus. Wo immer Sie diesen Wert festlegen, müssen Sie jQuery auch anweisen, ihn auszulösen.

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

sollte wie erwartet funktionieren.

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

Tarun Gupta
quelle
1
Funktioniert nicht für mich ... Wie könnte es überhaupt möglich sein, Werte in ein verstecktes Feld einzufügen? : /
Simon Dugré
Hey Danke, Paste sollte nicht da sein, aber Änderung kann das versteckte
Feldänderungsereignis
@KrisErickson Danke für die Geige, ich habe den Code aktualisiert, damit er die Änderung explizit erkennen kann. Bitte folgen Sie der aktualisierten Geige jsfiddle.net/7CM6k/3
Tarun Gupta
1
@TarunGupta Ja, es funktioniert am Trigger, aber es ändert den Wert nicht. Browser lösen das Änderungsereignis nicht aus, wenn der Wert eines versteckten Ereignisses geändert wird. Sie müssen dies manuell tun.
Kris Erickson
Der erste Teil dieser Antwort über die Bindung an alle versteckten Felder war sehr hilfreich. Vielen Dank!
Tschad
6
$('#userid').change(function(){
  //fire your ajax call  
});

$('#userid').val(10).change();
Digambar Patil
quelle
4

Es ist möglich, die Object.defineProperty()Eigenschaft 'value' des Eingabeelements neu zu definieren und während seiner Änderung alles zu tun.

Object.defineProperty() ermöglicht es uns, einen Getter und Setter für eine Eigenschaft zu definieren und diese so zu steuern.

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/

Viktar Tserashchuk
quelle
1
Ich mag diesen Ansatz, vor allem, weil alle anderen antworten: "Die Veränderung selbst auslösen" ... was nicht immer machbar ist.
sMyles
1
Das funktioniert fast für mich, alles außer dem endgültigen Wert im ausgeblendeten Feld wird nicht geändert. Wenn Sie die jsfiddle aktivieren, ändert sich der Wert des ausgeblendeten Felds nicht von '123' (mit Chrome)
MetaGuru
Sehr nah dran, aber wie die anderen bereits erwähnt haben, wird kein Verweis auf den ursprünglichen Mutator / Setter für das Feld beibehalten, sodass Aktualisierungen die versteckte Eingabe selbst nicht beeinflussen. Ich poste eine neue Lösung, die Teile dieses Ansatzes und die von stackoverflow.com/a/38802602/4342230
GuyPaddock
0

In diesem Beispiel wird der Wert des Entwurfsfelds jedes Mal zurückgegeben, wenn das ausgeblendete Entwurfsfeld seinen Wert ändert (Chrome-Browser):

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

       }
  };
})();
user2677034
quelle
0

Aufbauend auf der Antwort von Viktar können Sie eine Implementierung eines bestimmten versteckten Eingabeelements einmal aufrufen, um sicherzustellen, dass nachfolgende Änderungsereignisse ausgelöst werden, wenn sich der Wert des Eingabeelements ändert:

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

Nennen Sie dies auf Dokument fertig wie folgt:

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

Obwohl dieser Thread 3 Jahre alt ist, ist hier meine Lösung:

$(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");
    });
}
mdbxz
quelle
3
Das Unschärfeereignis wird nur ausgelöst, wenn die Eingabe den Fokus verliert. Ist keine gültige Antwort für eine versteckte Eingabe
Manuerumx