【问题标题】:Directive to update a datepicker does not update model更新日期选择器的指令不会更新模型
【发布时间】:2017-10-30 11:58:26
【问题描述】:

我在一个 angularjs 项目中使用来自 https://github.com/uxsolutions/bootstrap-datepicker 的时间选择器。

html 看起来像:

<div uxdatepicker ng-model="selectedDate"
  data-provide="datepicker-inline" ng-change="on_date_changed()">
</div>

我创建了如下指令:

app.directive("uxdatepicker", function ()
{
    return {
        require: "ngModel",
        scope: {
            ngModel: '='
        },
        link: function (scope, element, attrs, controller)
        {
            element.datepicker({
                language: "no",
                format: "yyyy-mm-dd",
                datesDisabled : ["2017-10-10"],
                maxViewMode: "days"
            }).on("changeDate", function (e)
            {
                scope.$apply(function ()
                {
                    controller.$setViewValue(e.date);
                });
            });
        }
    };
});

但我的主控制器中的 $scope.selectedDate 永远不会更新为所选日期。

为什么不呢?

我已在更改日期处理程序中提醒 e.date 以确保它包含所选日期。

【问题讨论】:

  • 我想删除这个问题,因为错误在别处。我在 ng-repeat 中有 uxdatepicker,它似乎无法在那里修改 $scope.selectedDate。相反,我使用了 e.selectedDate,其中 e 是 ng-repeat 项。

标签: angularjs datepicker


【解决方案1】:

我编写了以下指令以使其工作:

app.directive('wmAiGridDatePicker', ['$timeout', '$parse', function ($timeout, $parse) {
        return {//this datePicker will show the date in the wanted format and save it (ng-model) with the default format of yy-mm-dd
            template: '<input type="text"  style="cursor: pointer;border-color: rgb(239, 239, 239);height: 22px;padding-left: 6px;margin-right: 13px;margin-top: 10px;">',
            replace: true,
            require: 'ngModel',
            scope: {},
            link: function (scope, element, attrs, controller) {

                scope.time = {
                    hours: 0,
                    minutes: 0
                };

                var getModel = function () {
                    return controller.$modelValue;
                };

                var options = {
                    format: "dd/mm/yyyy"
                    , autoclose: 'true'                            
                    , todayBtn: "linked"
                    ,todayHighlight:true
                };

                element.datepicker(options);

                element.datepicker().on('hide', function () {

                    $timeout(function () {
                        var date_ = element.datepicker('getDate');

                        if (date_) {
                            date_.setHours(scope.time.hours);
                            date_.setMinutes(scope.time.minutes);                            
                            controller.$setViewValue(moment(date_).unix());
                        }


                        scope.$apply();
                    }, 1);
                });

                element.datepicker().on('changeDate', function () {

                    $timeout(function () {
                        var date_ = element.datepicker('getDate');

                        if (date_) {
                            date_.setHours(scope.time.hours);
                            date_.setMinutes(scope.time.minutes);
                            controller.$setViewValue(moment(date_).unix());
                        }


                        scope.$apply();
                    }, 1);
                });

                scope.onModelChange = function () {                   

                    var date = controller.$modelValue;

                    if (angular.isDate(date)) {
                        scope.time.hours = date.getHours();
                        scope.time.minutes = date.getMinutes();
                    }
                };

                controller.$render = function () {
                    var unixDate = controller.$modelValue;

                    if (!unixDate) {
                        return;
                    }

                    var date = new Date(unixDate * 1000);

                    if (angular.isDate(date)) {
                        scope.time.hours = date.getHours();
                        scope.time.minutes = date.getMinutes();
                    }

                    element.datepicker('setDate', date);
                    element.datepicker('update');
                };

                scope.$watch(getModel, function (newVal) {                    
                    scope.onModelChange();                 
                }, true);

                if (controller) {
                    controller.$render();
                }
            }
        };
    }]);

和 HTML:

<wm-date-picker  
    ng-blur="onChange()" 
    data-ng-model="item.due">
</wm-date-picker>

【讨论】:

  • 我真的需要制作手表吗?
  • @AndersLindén 好吧,你需要听听你的模型,我在 2-3 年前编写了这段代码,也许在最新的 1.6.7 中发生了一些变化。无论如何,它可以给你正确的方向。
  • 没有$timeout可以做到这一点吗?
  • @AndersLindén 通常$timeout 在触发下一个摘要周期之前将事件放到队列末尾。我相信scope.$apply(); 应该可以完成这项工作,但您可以检查一下
  • @AndersLindén 因为ng-repeat 的每个项目都有自己的范围。您可以使用$root a.e: '$root.myModel' inside ng-repeat 来引用范围
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-03
  • 1970-01-01
  • 2017-07-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多