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.