【问题标题】:AngularJS date picker firing onchange event multiple timesAngularJS 日期选择器多次触发 onchange 事件
【发布时间】:2014-06-03 02:21:23
【问题描述】:

我一直在为 Angularjs 寻找合适的日期选择器并决定使用 pickadate.js

http://amsul.ca/pickadate.js/

因为它漂亮的移动 UI 以及自定义指令以允许角度集成,如本博文所示

http://www.codinginsight.com/angularjs-and-pickadate/

我想扩展上述博客文章中的指令,并在值更改时在我的控制器中调用一个函数。扩展指令的完整代码如下所示

angular.module('plunker').directive('pickADate', function () {
    return {
        restrict: "A",
        scope: {
            pickADate: '=',
            minDate: '=',
            maxDate: '=',
            change: '='
        },
        link: function (scope, element, attrs) {
            element.pickadate({
                onSet: function (e) {
                    if (scope.$$phase || scope.$root.$$phase) // we are coming from $watch or link setup
                        return;
                    var select = element.pickadate('picker').get('select'); // selected date
                    scope.$apply(function () {
                        if (e.hasOwnProperty('clear')) {
                            scope.pickADate = null;
                            return;
                        }
                        if (!scope.pickADate)
                            scope.pickADate = new Date(0);
                        scope.pickADate.setYear(select.obj.getFullYear());
                        // Interesting: getYear returns only since 1900. Use getFullYear instead.
                        // It took me half a day to figure that our. Ironically setYear()
                        // (not setFullYear, duh) accepts the actual year A.D.
                        // So as I got the $#%^ 114 and set it, guess what, I was transported to ancient Rome 114 A.D.
                        // That's it I'm done being a programmer, I'd rather go serve Emperor Trajan as a sex slave.
                        scope.pickADate.setMonth(select.obj.getMonth());
                        scope.pickADate.setDate(select.obj.getDate());
                    });
                },
                onClose: function () {
                    element.blur();
                }
            });
            function updateValue(newValue) {
                if (newValue) {
                    scope.pickADate = (newValue instanceof Date) ? newValue : new Date(newValue);
                    // needs to be in milliseconds
                    element.pickadate('picker').set('select', scope.pickADate.getTime());
                } else {
                    element.pickadate('picker').clear();
                    scope.pickADate = null;
                }
            }
            updateValue(scope.pickADate);
            element.pickadate('picker').set('min', scope.minDate ? scope.minDate : false);
            element.pickadate('picker').set('max', scope.maxDate ? scope.maxDate : false);
            scope.$watch('pickADate', function (newValue, oldValue) {
                if (newValue == oldValue)
                    return;
                updateValue(newValue);

                // call change function
                scope.change;
            }, true);
            scope.$watch('minDate', function (newValue, oldValue) {
                element.pickadate('picker').set('min', newValue ? newValue : false);
            }, true);
            scope.$watch('maxDate', function (newValue, oldValue) {
                element.pickadate('picker').set('max', newValue ? newValue : false);
            }, true);
        }
    };
});

我现在可以将此指令与更改事件一起使用,如下所示在我的 HTML 中

<input type="text" pick-a-date="curDate" change="onChange()" />

它可以工作,但 OnChange 事件会为单个更改多次触发。关于如何让它只触发一次的任何想法?我创建了一个 plunker 来演示这个问题

http://plnkr.co/edit/3NcaAknd4GpelJxHWUyv

单击文本字段并选择一个日期。您将看到 counter 变量针对单个日期更改多次更新。

【问题讨论】:

    标签: angularjs datepicker angularjs-directive


    【解决方案1】:

    正如@miqid 建议在指令和控制器之间绑定函数使用'&amp;''=' 应仅用于绑定指令和控制器之间的范围变量。)

    此外,还必须对您当前的代码进行另一项更改。 updateValue() 中的函数 scope.change 没有被执行,因为它被称为 scope.change。这必须更改为scope.change()

    我已经分叉了您的 plunker 并对其进行了修改以修复上述更改。

    固定工作插件:http://plnkr.co/edit/oEpOxE21dXre28FpKoMc?p=preview

    计数器只更新一次以进行更改。让我知道这是否有帮助。

    【讨论】:

      【解决方案2】:

      您已使用'=' 而不是'&amp;'pick-a-date 指令中绑定change

      建议将后一种隔离范围绑定用于回调函数等表达式。

      来自 directives 的 AngularJS 文档的相关建议:

      最佳实践:当您希望指令公开 API 以绑定到行为时,请在范围选项中使用 &amp;attr

      【讨论】:

        猜你喜欢
        • 2012-01-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-03
        相关资源
        最近更新 更多