jQuery UI日期选择器onchange事件问题

269

我有一段JS代码,在更改字段时会调用搜索程序。问题在于,我找不到任何jQuery事件,可以在Datepicker更新输入字段时触发。

由于某种原因,当Datepicker更新字段时,不会调用“change”事件。当日历弹出时,它会改变焦点,因此我也无法使用它。你有什么想法吗?


我最终使用了https://dev59.com/KV0a5IYBdhLWcg3wmZzC#30132949,因为它似乎直接回答了这个问题。 - twobob
19个回答

406
您可以使用日期选择器的onSelect事件
$(".date").datepicker({
    onSelect: function(dateText) {
        console.log("Selected date: " + dateText + "; input's current value: " + this.value);
    }
});

实时演示:

$(".date")
.datepicker({
    onSelect: function(dateText) {
        console.log("Selected date: " + dateText + "; input's current value: " + this.value);
    }
})
.on("change", function() {
    console.log("Got change event from field");
});
<link href="https://code.jquery.com/ui/1.9.2/themes/smoothness/jquery-ui.css" rel="stylesheet" />
<input type='text' class='date'>
<script src="https://code.jquery.com/jquery-1.8.3.min.js"></script>
<script src="https://code.jquery.com/ui/1.9.2/jquery-ui.js"></script>

很不幸,onSelect事件在选择日期时总是触发,即使日期未改变也是如此。这是日期选择器的一个设计缺陷:它总是触发onSelect(即使没有任何更改),并且在输入框上不会触发任何更改事件。(如果您查看示例代码,我们正在监听更改事件,但它们没有被触发。)当事情改变时,它应该在输入框上触发一个事件(可能是通常的change事件,或者可能是一个特定于日期选择器的事件)。


如果需要,您当然可以让input元素上的change事件触发:

$(".date").datepicker({
    onSelect: function() {
        $(this).change();
    }
});

这将会触发 jQuery 钩子上所有处理程序的基础 inputchange 事件。但是,它总是触发。如果您只想在实际更改时触发,请保存先前的值(可能通过data)并进行比较。

现场示例

$(".date")
.datepicker({
    onSelect: function(dateText) {
        console.log("Selected date: " + dateText + "; input's current value: " + this.value);
        $(this).change();
    }
})
.on("change", function() {
    console.log("Got change event from field");
});
<link href="https://code.jquery.com/ui/1.9.2/themes/smoothness/jquery-ui.css" rel="stylesheet" />
<input type='text' class='date'>
<script src="https://code.jquery.com/jquery-1.8.3.min.js"></script>
<script src="https://code.jquery.com/ui/1.9.2/jquery-ui.js"></script>


2
我已经在不同的场景中反复尝试了很多次,而这个方法终于解决了问题!非常感谢! - Chris Nevill
8
为什么他们没有真实地呈现这些事件? - Jay K
1
这是用于“选择”,而不是“更改”。如果您选择一个日期,然后重新选择它,此事件将被触发。一些开发人员希望知道日期是否已从某个初始状态更改,以确定数据是否“脏”并需要保存。出于这个原因,我在这个问题上给你投了反对票。 - Johann
4
@AndroidDev:我已经澄清了。 当然,你也可以做到;该网站的目标是拥有好的答案;鼓励进行尊重的编辑以实现这一目标。 这是日期选择器的设计缺陷,而不是回答的问题。(它应该在仅在更改日期时才对输入触发某种更改事件,但它没有这样做。) - T.J. Crowder
5
如果日期选择器已经被初始化,请使用以下代码:$(".date").datepicker('option', 'onSelect', function() { $(this).change(); });。这将在选择日期时触发一个change事件。 - Brad Denver
显示剩余8条评论

78
T.J. Crowder的回答(https://dev59.com/Tmw15IYBdhLWcg3wqNgA#6471992)非常好,仍然保持准确。但是,在onSelect函数内触发change事件是你可能会遇到的最接近的情况。然而,datepicker对象上有一个很好的属性(lastVal),它将允许你有条件地仅在实际更改时触发change事件,而无需自己存储值。
$('#dateInput').datepicker({
     onSelect: function(d,i){
          if(d !== i.lastVal){
              $(this).change();
          }
     }
});

然后像平常一样处理更改事件:
$('#dateInput').change(function(){
     //Change code!
});

1
有人最近测试过这个吗?对我来说它不起作用。i.lastVal返回未定义,并且它似乎不是可用属性之一。 - B.K.
我刚刚实现了这个,没有任何问题。运行得非常好。 - DevSlick
这个不再起作用了,lastval不再被定义。 - luke_mclachlan
5
"lastVal" 但是就是这样;-) - Alexander Derck
1
在我的测试中,datepicker对象上不存在lastVal,因此此解决方案将始终触发更改。 - Nicholas Head
显示剩余2条评论

15

你正在寻找日期选择器对象中的onSelect事件:

$('.selector').datepicker({
   onSelect: function(dateText, inst) { ... }
});

13
$('#inputfield').change(function() { 
    dosomething();
});

17
我原以为这会起作用,但不幸的是它没有。只有在使用键盘更改字段时才会触发,而不是从日期选择器中选择时触发。很烦人。 - Simon East
1
从jQuery UI文档中: "此小部件通过编程方式操作其元素的值,因此当元素的值发生变化时,可能不会触发原生的change事件。" - Sam Kauffman
有趣的是,我得到了相反的结果 - 当我通过键盘手动更改输入时,不会触发任何事件。但是当我通过小部件更改字段的值时,更改事件会被触发。奇怪。 - Geeky Guy
当我使用键盘或日期选择器部件更改时,这很好用。 - The Sammie
2
这个函数被多次调用了。 - NMathur

12

我写这篇文章是因为需要一个只在日期改变时触发事件的解决方案。

这是一个简单的解决方案。每次对话框关闭时,我们测试是否已更改数据。如果已更改,则触发自定义事件并重置存储的值。

$('.datetime').datepicker({
    onClose: function(dateText,datePickerInstance) {
        var oldValue = $(this).data('oldValue') || "";
        if (dateText !== oldValue) {
            $(this).data('oldValue',dateText);
            $(this).trigger('dateupdated');
        }
    }
});

现在我们可以为这个自定义事件挂钩处理程序...

$('body').on('dateupdated','.datetime', function(e) {
    // do something
});

我正在使用它与knockout,但我无法让它在用户未选择日期时触发事件,而是手动更改了日期。非常有帮助。 - Tony
我的问题与jQuery日期选择器字段不完全相同,与此处发布的问题不同。它涉及更改事件多次触发的问题。我尝试了几种解决方案,这是唯一在我的情况下实际起作用的解决方案。 - Patee Gutee
我做的和这个解决方案差不多,我认为它绝对是最好的。我会在另一个答案中发布我的做法... - user7168530

11

5

请尝试:

$('#idPicker').on('changeDate', function() {
    var date = $('#idPicker').datepicker('getFormattedDate');
});

5

我知道这是一个老问题。但是我无法在onSelect事件中正确地触发jquery $(this).change()事件。所以我采用了以下方法通过vanilla js触发change事件。

$('.date').datepicker({
     showOn: 'focus',
     dateFormat: 'mm-dd-yy',
     changeMonth: true,
     changeYear: true,
     onSelect: function() {
         var event;
         if(typeof window.Event == "function"){
             event = new Event('change');
             this.dispatchEvent(event);
         }   else {
             event = document.createEvent('HTMLEvents');
             event.initEvent('change', false, false);
             this.dispatchEvent(event);
         }
     }
});

这段代码出现错误:“'$'未定义”。噢。 - Michael12345
您正在onSelect事件中分派一个change事件,这并不是期望的效果,因为每次单击日期时都会触发select事件,但这并不一定意味着日期实际上已更改,即用户可能两次单击相同的日期。 - Jacques
@Jacques,您是正确的。我相信您可以将String dateText与this.value进行比较,只有在它们不同时才会触发此操作。 - tstrand66
@Michael12345 我明白你的意思。我已经修改了它,使其不再是片段。对此我深表歉意。 - tstrand66

4

试试这个

$('#dateInput').datepicker({
 onSelect: function(){
       $(this).trigger('change');
      }
 }});

希望这能帮到你:)

4
在jQueryUi 1.9中,我通过额外的数据值和beforeShow和onSelect函数的组合来使其工作:
$( ".datepicker" ).datepicker({
    beforeShow: function( el ){
        // set the current value before showing the widget
        $(this).data('previous', $(el).val() );
    },

    onSelect: function( newText ){
        // compare the new value to the previous one
        if( $(this).data('previous') != newText ){
            // do whatever has to be done, e.g. log it to console
            console.log( 'changed to: ' + newText );
        }
    }
});

对我来说没问题 :)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接