jQuery - Phát hiện thay đổi giá trị trên trường đầu vào ẩn


270

Tôi có một trường văn bản ẩn có giá trị được cập nhật thông qua phản hồi AJAX.

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

Khi giá trị này thay đổi, tôi muốn thực hiện yêu cầu AJAX. Bất cứ ai có thể tư vấn làm thế nào để phát hiện sự thay đổi?

Tôi có đoạn mã sau, nhưng không biết cách tìm giá trị:

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

2
Nếu nó được cập nhật thông qua phản hồi ajax, tại sao bạn không kích hoạt yêu cầu ajax mới trong chức năng thành công của phản hồi?
BonyT

2
$ ('# userid'). val () sẽ cung cấp cho bạn giá trị nếu đó là những gì bạn đang hỏi
BonyT

CẬP NHẬT: một sự kiện thay đổi hiện được kích hoạt khi giá trị của một trường ẩn được cập nhật.
Steven

Câu trả lời:


622

Vì vậy, điều này là muộn, nhưng tôi đã phát hiện ra một câu trả lời, trong trường hợp nó trở nên hữu ích cho bất kỳ ai đi qua chủ đề này.

Thay đổi giá trị thành các phần tử ẩn không tự động kích hoạt sự kiện .change (). Vì vậy, bất cứ nơi nào bạn đặt giá trị đó, bạn cũng phải báo cho jQuery để kích hoạt nó.

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

Một khi đó là trường hợp,

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

Nên làm việc như mong đợi.


5
.trigger()thường tốt hơn để sử dụng hơn chỉ gọi change()?
Hanna

1
Nó hoạt động, nhưng có vẻ như nó kích hoạt sự kiện thay đổi hai lần!. Giống như nếu tôi đặt mã này, nó sẽ mã hóa hai lần, nếu tôi xóa mã, không có trình kích hoạt nào. !!
Janx từ Venezuela

1
Để làm cho nó hoạt động giống như changesự kiện, bạn nên thêm mã vào setUserID()để kiểm tra xem giá trị có thực sự thay đổi hay không. if ($('#userid').val() != myVaule) { // set val() and trigger change }
nnattaw

1
Điều này đặc biệt hữu ích nếu bạn đang cố gắng bắt sự kiện "thay đổi" khi được thay đổi thông qua javascript, nếu không, những thay đổi được tạo bởi javascript có thể bị bắt bởi .change (handler) hoặc .on ("change", handler)
JJK

7
Vì vậy, nếu tôi không có quyền kiểm soát chức năng thay đổi giá trị của trường ẩn (nghĩa là không thể kích hoạt trình kích hoạt), giải pháp này sẽ không hoạt động, phải không?
osama yaccoub

31

Vì đầu vào ẩn không kích hoạt sự kiện "thay đổi" khi thay đổi, tôi đã sử dụng M mutObserver để kích hoạt sự kiện này.

(Đôi khi thay đổi giá trị đầu vào bị ẩn được thực hiện bởi một số tập lệnh khác mà bạn không thể sửa đổi)

Điều này không hoạt động trong IE10 trở xuống

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 máy chủ đột biến cũng KHÔNG bị sa thải vì thay đổi bên trong trường văn bản (bất kể có bị ẩn hay không)
Ole Albers

3
Hoạt động tuyệt vời! @OleAlbers - OP đã hỏi vềinput[type=hidden]
Shay

1
Tôi đã sử dụng kết hợp với một chức năng sử dụng lệnh ánh xạ của jquery để lấy một tập hợp các giá trị trường đầu vào ẩn. Cảm ơn rất nhiều @lulalala!
AdamJones

2
Đơn giản và dễ hiểu. Giải pháp này, trái ngược với giải pháp "bạn phải kích hoạt sự kiện khi bạn thay đổi giá trị", không phụ thuộc vào lập trình viên có quyền truy cập vào mã tại điểm thay đổi giá trị, làm cho nó hữu ích hơn miễn là bạn không Không phải hỗ trợ phiên bản cũ hơn IE11. Nó làm việc rất lớn đối với tôi. Cảm ơn
Joe Salazar

Giải pháp tuyệt vời! Cảm ơn bạn! Vì một số lý do, trigger('change')nó không hoạt động với tôi, vì vậy tôi đã tạo CustomEvent, đăng ký và sau đóelement.dispatchEvent(myCustomEvent)
tbutcaru

8

Bạn chỉ có thể sử dụng chức năng dưới đây, Bạn cũng có thể thay đổi thành phần loại.

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

Thay đổi giá trị thành các phần tử ẩn không tự động kích hoạt sự kiện .change (). Vì vậy, bất cứ nơi nào bạn đặt giá trị đó, bạn cũng phải báo cho jQuery để kích hoạt nó.

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

Nên làm việc như mong đợi.

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


1
Không hoạt động với tôi ... Dù sao đi nữa, làm sao có thể dán giá trị vào Trường ẩn? : /
Simon Dugré

Xin cảm ơn, dán không nên ở đó, nhưng thay đổi có thể phát hiện sự kiện thay đổi trường ẩn
Tarun Gupta

@KrisErickson Cảm ơn về fiddle, tôi đã cập nhật mã để nó có thể phát hiện ra sự thay đổi một cách rõ ràng, Vui lòng làm theo fiddle cập nhật jsfiddle.net/7CM6k/3
Tarun Gupta

1
@TarunGupta yeah nó hoạt động trên trình kích hoạt, nhưng không thay đổi giá trị. Các trình duyệt không kích hoạt sự kiện thay đổi khi ẩn có giá trị thay đổi, bạn phải thực hiện thủ công.
Kris Erickson

Phần đầu tiên của câu trả lời này về sự ràng buộc với tất cả các trường ẩn là rất hữu ích. Cảm ơn!
Chad

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

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

4

Có thể sử dụng Object.defineProperty()để xác định lại thuộc tính 'giá trị' của phần tử đầu vào và làm bất cứ điều gì trong quá trình thay đổi.

Object.defineProperty() cho phép chúng ta định nghĩa một getter và setter cho một thuộc tính, do đó kiểm soát nó.

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
Tôi thích cách tiếp cận này, đặc biệt vì câu trả lời của mọi người khác là "tự kích hoạt thay đổi" ... điều này không phải lúc nào cũng khả thi.
sMstyle

1
điều này gần như làm việc với tôi, mọi thứ trừ giá trị cuối cùng trong trường ẩn thực sự không bị thay đổi, nếu bạn kiểm tra jsfiddle thì giá trị trường ẩn không thay đổi từ '123' (sử dụng Chrome)
MetaGuru

Rất gần, nhưng như những người khác đã đề cập, nó không duy trì tham chiếu đến trình biến đổi / setter gốc cho trường, vì vậy các cập nhật không ảnh hưởng đến chính đầu vào ẩn. Tôi đang đăng một giải pháp mới kết hợp các phần của phương pháp này và một giải pháp từ stackoverflow.com/a/38802602/4342230
GuyPaddock

0

Ví dụ này trả về giá trị trường dự thảo mỗi khi trường dự thảo ẩn thay đổi giá trị của nó (trình duyệt 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

Dựa trên câu trả lời của Viktar , đây là một triển khai bạn có thể gọi một lần trên phần tử đầu vào ẩn đã cho để đảm bảo rằng sự kiện thay đổi tiếp theo sẽ được kích hoạt bất cứ khi nào giá trị của phần tử đầu vào thay đổi:

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

Gọi đây trên tài liệu đã sẵn sàng như vậy:

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

-4

Mặc dù chủ đề này đã 3 tuổi, đây là giải pháp của tôi:

$(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
sự kiện mờ chỉ được kích hoạt khi đầu vào mất tiêu điểm. Không phải là một phản hồi hợp lệ cho một đầu vào ẩn
manuerumx
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.