jQuery - Визначення зміни значення в прихованому полі введення


270

У мене є приховане текстове поле, значення якого оновлюється за допомогою відповіді AJAX.

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

Коли це значення змінюється, я б хотів запустити запит AJAX. Хтось може порадити, як виявити зміну?

У мене є такий код, але я не знаю, як шукати значення:

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

2
Якщо він оновлюється за допомогою відповіді ajax, чому б вам просто не запустити новий запит ajax у функції успіху відповіді?
BonyT

2
$ ('# userid'). val () дасть вам значення, якщо про це ви запитуєте
BonyT

ОНОВЛЕННЯ: подія зміни зараз запускається, коли значення прихованого поля оновлюється.
Стівен

Відповіді:


622

Отже, це вже пізно, але я виявив відповідь, якщо він стане в нагоді кожному, хто натрапив на цю нитку.

Зміни значення прихованих елементів не автоматично запускають подію .change (). Отже, де б ви не встановлювали це значення, ви також повинні сказати jQuery, щоб його запустити.

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

Коли це так,

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

повинні працювати, як очікувалося.


5
Є чи .trigger()взагалі краще використовувати більш просто дзвоню change()?
Ганна

1
Це працює, але здається, що він запускає подію зміни двічі !. Це як якщо я поставив цей код, він трепетить його двічі, якщо я видаляю код, жодних тригерів не буде.
Янкс з Венесуели

1
Щоб він поводився так само, як і changeподія, слід додати код, setUserID()щоб перевірити, чи дійсно значення змінюється чи ні. if ($('#userid').val() != myVaule) { // set val() and trigger change }
nnattawat

1
Це особливо корисно, якщо ви намагаєтеся зафіксувати подію "зміни", яка змінюється через javascript, інакше зміни, внесені javascript, не можуть бути схоплені .change (обробником) або .on ("змінити", обробником)
JJK

7
Так що якщо я не маю управління функцією, яка змінює значення прихованого поля (тобто не можу запустити тригер), це рішення не буде працювати, правда?
osama yaccoub

31

Оскільки прихований вхід не викликає події "change" на зміну, я використовував MutationObserver, щоб запустити це.

(Іноді приховані зміни вхідного значення здійснюються деякими іншими сценаріями, які ви не можете змінити)

Це не працює в IE10 та нижче

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 також НЕ звільняється за зміну всередині текстового поля (незалежно від того, прихований він чи ні)
Оле Альберс

3
Чудово працює! @OleAlbers - ОП запитав проinput[type=hidden]
Шай

1
Я використовував це в поєднанні з функцією, яка використовувала команду map jquery для отримання колекції прихованих значень поля введення. Велике спасибі @lulalala!
AdamJones

2
Простий і легкий для розуміння. Це рішення, на відміну від рішення "ви повинні викликати подію, коли ви змінюєте значення", не покладається на те, що програміст має доступ до коду в точці, коли значення змінюється, що робить його більш корисним, доки ви не я не повинен підтримувати версію, старшу за IE11. Це чудово працювало для мене. Дякую
Джо Салазар

Чудове рішення! Дякую! Чомусь trigger('change')це не спрацювало для мене, тому я створив CustomEvent, зареєстрував його і потімelement.dispatchEvent(myCustomEvent)
tbutcaru

8

Ви можете просто скористатися наведеною нижче функцією. Ви також можете змінити елемент типу.

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

Зміни значення прихованих елементів не автоматично запускають подію .change (). Отже, де б ви не встановлювали це значення, ви також повинні сказати jQuery, щоб його запустити.

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

повинні працювати, як очікувалося.

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


1
Не працює для мене ... У будь-якому разі, як можна було вставити значення у Приховане поле? : /
Simon Dugré

Привіт, спасибі, пасти не повинно бути там, але зміна може виявити приховану подію зміни поля
Тарун Гупта,

@KrisErickson Дякую за загадку, я оновив код, щоб він міг чітко визначити зміни. Будь ласка, слідкуйте за оновленою загадкою jsfiddle.net/7CM6k/3
Tarun Gupta

1
@TarunGupta так, він працює на тригері, але не змінює значення. Веб-переглядачі не запускають подію зміни, коли прихований змінив її значення, це потрібно зробити вручну.
Кріс Еріксон

Перша частина цієї відповіді про прив’язку до всіх прихованих полів була дуже корисною. Дякую!
Чад


4

Можна використовувати Object.defineProperty()для того, щоб перевизначити властивість 'value' вхідного елемента і зробити що-небудь під час його зміни.

Object.defineProperty() дозволяє нам визначити getter та setter для властивості, контролюючи, таким чином.

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
Мені подобається такий підхід, тим більше, що відповідь усіх інших - "спровокувати зміни" ... що не завжди можливо.
sMyles

1
це майже працює для мене, все, окрім остаточного значення в прихованому полі, насправді не змінюється, якщо ви перевіряєте jsfiddle, то значення прихованого поля не змінюється від "123" (за допомогою Chrome)
MetaGuru

Дуже близько, але, як згадували інші, він не підтримує посилання на оригінальний мутатор / сетер для цього поля, тому оновлення не впливає на прихований вхід. Я відправляю нове рішення , яке включає в себе частину цього підходу і один з stackoverflow.com/a/38802602/4342230
GuyPaddock

0

Цей приклад повертає значення поля чернетки щоразу, коли приховане чернече поле змінює своє значення (хромований браузер):

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

Опираючись на відповідь Віктора , ось реалізація, яку ви можете один раз зателефонувати на заданий прихований вхідний елемент, щоб гарантувати, що наступна подія зміни буде звільнена, коли значення елемента введення змінюється:

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

Назвіть це на готовий документ так:

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

-4

Хоча цій темі вже 3 роки, ось моє рішення:

$(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
подія розмивання запускається лише тоді, коли вхід втрачає фокус. Не є коректною відповіддю на прихований вхід
manuerumx
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.