jQuery: rileva la modifica del valore nel campo di input nascosto


270

Ho un campo di testo nascosto il cui valore viene aggiornato tramite una risposta AJAX.

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

Quando questo valore cambia, vorrei inviare una richiesta AJAX. Qualcuno può consigliare su come rilevare il cambiamento?

Ho il seguente codice, ma non so come cercare il valore:

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

2
Se viene aggiornato tramite una risposta Ajax, perché non lanciare semplicemente la nuova richiesta Ajax nella funzione di successo della risposta?
BonyT,

2
$ ('# userid'). val () ti darà il valore se è quello che stai chiedendo
BonyT

AGGIORNAMENTO: ora viene attivato un evento di modifica quando viene aggiornato il valore di un campo nascosto.
Steven,

Risposte:


622

Quindi è molto tardi, ma ho scoperto una risposta, nel caso in cui diventi utile per chiunque incontri questo thread.

Le modifiche di valore agli elementi nascosti non generano automaticamente l'evento .change (). Quindi, ovunque sia che stai impostando quel valore, devi anche dire a jQuery di attivarlo.

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

Una volta che è il caso,

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

dovrebbe funzionare come previsto.


5
In .trigger()genere è meglio usare solo telefonando change()?
Hanna,

1
Funziona, ma sembra che inneschi due volte l'evento change !. È come se inserissi questo codice, lo fa scattare due volte, se rimuovo il codice, nessun trigger w / e. !!
Janx dal Venezuela,

1
Per farlo si comporta come un changeevento, è necessario aggiungere il codice setUserID()per verificare se il valore è realmente cambiato o meno. if ($('#userid').val() != myVaule) { // set val() and trigger change }
nnattawat,

1
Ciò è particolarmente utile se si sta tentando di rilevare un evento "change" che viene modificato tramite javascript, altrimenti le modifiche apportate da javascript non possono essere rilevate dal .change (gestore) o .on ("cambiamento", gestore)
JJK,

7
quindi se non ho il controllo sulla funzione che modifica il valore del campo nascosto (cioè non posso attivare il trigger), questa soluzione non funzionerà, giusto?
Osama Yaccoub,

31

Poiché l'input nascosto non attiva l'evento "change" in caso di modifica, ho utilizzato invece MutationObserver per attivare questo.

(A volte le modifiche al valore di input nascosto vengono apportate da alcuni altri script che non è possibile modificare)

Questo non funziona in IE10 e versioni precedenti

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

Anche AFAIK il mutationobserver NON viene licenziato in caso di modifica all'interno di un campo di testo (non importa se nascosto o no)
Ole Albers,

3
Funziona alla grande! @OleAlbers - OP ha chiesto diinput[type=hidden]
Shay

1
L'ho usato in combinazione con una funzione che utilizzava il comando map di jquery per recuperare una raccolta di valori di campi di input nascosti. Grazie mille @lulalala!
Adam Jones

2
Semplice e facile da capire Questa soluzione, al contrario delle soluzioni "è necessario attivare l'evento quando si modifica il valore", non si basa sul fatto che il programmatore abbia accesso al codice nel punto in cui il valore viene modificato, rendendolo più utile finché non si non è necessario supportare una versione precedente a IE11. Ha funzionato benissimo per me. Grazie
Joe Salazar,

Ottima soluzione! Grazie! Per qualche motivo trigger('change')non ha funzionato per me, quindi ho creato un CustomEvent, l'ho registrato e poielement.dispatchEvent(myCustomEvent)
tbutcaru

8

Puoi semplicemente usare la seguente funzione, Puoi anche cambiare l'elemento del tipo.

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

Le modifiche di valore agli elementi nascosti non generano automaticamente l'evento .change (). Quindi, ovunque sia che stai impostando quel valore, devi anche dire a jQuery di attivarlo.

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

dovrebbe funzionare come previsto.

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


1
Non funziona per me ... Comunque, come è possibile incollare valore in un campo nascosto? : /
Simon Dugré,

Ehi, grazie, la funzione di incolla non dovrebbe essere lì, ma il cambiamento può rilevare l'evento di cambio di campo nascosto
Tarun Gupta,

@KrisErickson Grazie per il violino, ho aggiornato il codice in modo che possa rilevare esplicitamente la modifica, segui il violino aggiornato jsfiddle.net/7CM6k/3
Tarun Gupta

1
@TarunGupta sì, funziona sul trigger, ma non cambia il valore. I browser non attivano l'evento change quando un valore nascosto è cambiato, devi farlo manualmente.
Kris Erickson,

La prima parte di questa risposta sull'associazione a tutti i campi nascosti è stata molto utile. Grazie!
Chad,

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

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

4

È possibile utilizzare Object.defineProperty()per ridefinire la proprietà 'value' dell'elemento di input e fare qualsiasi cosa durante la sua modifica.

Object.defineProperty() ci permette di definire un getter e setter per una proprietà, controllandola così.

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
Mi piace questo approccio, soprattutto perché la risposta di tutti è "innescare il cambiamento da soli" ... il che non è sempre fattibile.
sMyles,

1
questo funziona quasi per me, tutto tranne il valore finale nel campo nascosto non viene effettivamente modificato, se controlli jsfiddle il valore del campo nascosto non cambia da '123' (usando Chrome)
MetaGuru

Molto vicino, ma come hanno già detto gli altri, non mantiene un riferimento al mutatore / setter originale per il campo, quindi gli aggiornamenti non influiscono sull'input nascosto stesso. Sto postando una nuova soluzione che incorpora pezzi di questo approccio e quello da stackoverflow.com/a/38802602/4342230
GuyPaddock

0

Questo esempio restituisce il valore del campo bozza ogni volta che il campo bozza nascosto cambia il suo valore (browser Chrome):

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

Partendo dalla risposta di Viktar , ecco un'implementazione che puoi chiamare una volta su un dato elemento di input nascosto per garantire che l'evento di modifica successivo venga attivato ogni volta che cambia il valore dell'elemento di input:

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

Chiamalo sul documento pronto in questo modo:

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

-4

Sebbene questa discussione abbia 3 anni, ecco la mia soluzione:

$(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
l'evento sfocatura viene attivato solo quando l'ingresso perde la messa a fuoco. Non è una risposta valida per un input nascosto
manuerumx
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.