4

我正在将Eternicode's Bootstrap Datepicker集成到我的应用程序中。我不知道如何将它连接到我的模型,所以我发现了一个指令,使用它从here。现在我的页面上有日期选择器,但当点击输入字段时它不会保持打开状态。日期选择器几乎立即打开和关闭。如果我点击相邻的字段并将选项卡放入日期选择器字段,它将保持打开状态,如预期的那样。我也有问题得到它出现在我想要的地方。当它确实打开时,它是在一些其他元素之下并且不合适。它应该直接在输入字段下方打开。见下面的截图。Angular Bootstrap DatePicker指令(Eternicode版本)不会保持打开状态

misplaced

在我的控制,我有:

$scope.dateOptions = { 
    format: 'dd/mm/yyyy', 
    autoclose: false, 
    clearBtn: true, 
    container: '#datepicker', 
    showOnFocus: true, 
    startDate: new Date(), 
    todayBtn: true, 
    todayHighlight: true, 
    weekStart: 1, 
    zIndexOffset: 5000 
} 
$scope.newPost = { 
    token: $scope.token, 
    post: $scope.post, 
    posts: { 
     twitter: null, 
     facebook: null, 
     linkedin: null 
    }, 
    attachment_url: $scope.attachment_url, 
    media_url: $scope.media_url, 
    services: { 
     twitter: $scope.twitter, 
     facebook: $scope.facebook, 
     linkedin: $scope.linkedin 
    }, 
    dateObject: today, 
    timeObject: today 
}; 

然后在我的指导,我有:

.directive('bDatepicker', function(){ 
    return { 
     require: '?ngModel', 
     restrict: 'A', 
     link: function ($scope, element, attrs, controller) { 
      var updateModel, onblur; 

      if (controller != null) { 

       updateModel = function (event) { 
        element.datepicker('hide'); 
        element.blur(); 
       }; 

       onblur = function() { 
        //we'll update the model in the blur() handler 
        //because it's possible the user put in an invalid date 
        //in the input box directly. 
        //Bootstrap datepicker will have overwritten invalid values 
        //on blur with today's date so we'll stick that in the model. 
        //this assumes that the forceParse option has been left as default(true) 
        //https://github.com/eternicode/bootstrap-datepicker#forceparse 
        var date = element.val(); 
        return $scope.$apply(function() { 
         return controller.$setViewValue(date); 
        }); 
       }; 

       controller.$render = function() { 
        var date = controller.$viewValue; 
        if (angular.isDefined(date) && date != null && angular.isDate(date)) 
        { 
         element.datepicker().data().datepicker.date = date; 
         element.datepicker('setValue'); 
         element.datepicker('update'); 
        } else if (angular.isDefined(date)) { 
         throw new Error('ng-Model value must be a Date object - currently it is a ' + typeof date + ' - use ui-date-format to convert it from a string'); 
        } 
        return controller.$viewValue; 
       }; 
      } 
      return attrs.$observe('bDatepicker', function (value) { 
       var options; 
       options = { }; //<--- insert your own defaults here! 
       if (angular.isObject(value)) { 
        options = value; 
       } 
       if (typeof (value) === "string" && value.length > 0) { 
        options = angular.fromJson(value); 
       } 
       return element.datepicker(options).on('changeDate', updateModel).on('blur', onblur); 
      }) 
     } 
    } 
}); 

最后在我看来,我有:

<input b-datepicker="{{dateOptions}}" ng-model="newPost.dateObject" id="datepicker"> 

我创造了一个小提琴,但我无法让它正确地工作。我得到一个Uncaught Error: [$injector:modulerr]错误,我无法弄清楚如何解决。这里是链接:https://jsfiddle.net/kxge3cqf/

这里从`social_media_posts.json样品:

[ 
    { 
     id: 50, 
     company_id: 94, 
     employer_id: 3, 
     post: "testing without attachments", 
     attachment_url: null, 
     twitter: true, 
     facebook: false, 
     linkedin: false, 
     post_date: "Fri, Oct 30, 2015", 
     post_time: " 2:50 PM EDT" 
    }, 
    { 
     total_count: 1 
    } 
] 

这里是从groups.json样品:

{ 
    groups: { 
     1: { 
      id: 1, 
      name: "Human Resources", 
      created_at: "2015-10-27T16:23:07.287Z", 
      updated_at: "2015-11-01T16:11:43.329Z", 
      company_id: 94 
     }, 
     2: { 
      id: 2, 
      name: "Marketing", 
      created_at: "2015-11-01T15:32:28.988Z", 
      updated_at: "2015-11-01T16:11:43.354Z", 
      company_id: 94 
     } 
    } 
} 

这里从contacts.json样品:

{ 
    contacts: { 
     1: { 
      id: 1, 
      first_name: "Foo", 
      last_name: "Bar", 
      email: "[email protected]", 
      created_at: "2015-10-27T16:24:00.832Z", 
      updated_at: "2015-11-01T16:11:52.426Z", 
      company_id: 94 
     } 
    } 
} 
+0

你能提供一个小提琴吗? –

+0

我创建了一个小提琴,但我无法让它正常工作。我收到一个'未捕获的错误:[$ injector:modulerr]'错误,我无法弄清楚如何解决。这里是链接:https://jsfiddle.net/kxge3cqf/ – ACIDSTEALTH

+0

@ACIDSTEALTH我在本地环境中复制代码,并且'[$ injector:modulerr]'似乎是因为'angular.module('myApp',['ui .bootstrap'])',这里ui.bootstrap没有被定义,在从外部链接包含它之后,我又得到了'无法加载file:///contacts.json。 '和类似的groups.json和socila_media_posts.json,你可以提供这些文件或虚拟数据。所以我可以研究它。 但是,当我试图分开侦探部分和它有什么问题。 –

回答

2

这看起来像是你的问题

$event.stopPropagation(); 

angular.module('peskyDatepicker', ['ui.bootstrap']) 
 
.controller('DatepickerDemoCtrl', ['$scope', 
 
function ($scope) { 
 
    
 
    var vm = this; 
 
    
 
    vm.valuationDate = new Date(); 
 
    vm.valuationDatePickerIsOpen = false; 
 
    vm.opens = []; 
 
    
 
    $scope.$watch(function() { 
 
     return vm.valuationDatePickerIsOpen; 
 
    },function(value){ 
 
     vm.opens.push("valuationDatePickerIsOpen: " + value + " at: " + new Date()); 
 
    }); 
 
    
 
    vm.valuationDatePickerOpen = function ($event) { 
 
    
 
     if ($event) { 
 
      $event.preventDefault(); 
 
      $event.stopPropagation(); // This is the magic 
 
     } 
 
     this.valuationDatePickerIsOpen = true; 
 
    }; 
 
}]);
<!DOCTYPE html> 
 
<html ng-app="peskyDatepicker"> 
 

 
    <head> 
 
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script> 
 
    <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.13.0/ui-bootstrap-tpls.min.js"></script> 
 
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" /> 
 
    <link rel="stylesheet" href="style.css" /> 
 
    <script src="script.js"></script> 
 
    </head> 
 

 
    <body> 
 
    <div ng-controller="DatepickerDemoCtrl as vm"> 
 
     <pre>Selected date is: <em>{{vm.valuationDate | date:'fullDate' }}</em> 
 
     </pre> 
 
     <div class="row"> 
 
     <div class="col-md-3"> 
 
      <p class="input-group"> 
 
      <span class="input-group-btn"> 
 
       <button type="button" class="btn btn-default" 
 
         ng-click="vm.valuationDatePickerOpen()"> 
 
       <i class="glyphicon glyphicon-calendar"></i> 
 
       </button> 
 
      </span> 
 
      <input type="text" class="form-control" 
 
        datepicker-popup="mediumDate" 
 
        is-open="vm.valuationDatePickerIsOpen" 
 
        ng-click="vm.valuationDatePickerOpen()" 
 
        ng-model="vm.valuationDate" /> 
 
      <span class="input-group-btn"> 
 
       <button type="button" class="btn btn-default" 
 
         ng-click="vm.valuationDatePickerOpen($event)"> 
 
       <i class="glyphicon glyphicon-calendar"></i> 
 
       </button> 
 
      </span> 
 
      </p> 
 
     </div> 
 
     </div> 
 
     <p class="col-md-3"> 
 
     The left button <em>doesn't</em> work (opens the picker and closes right away).<br /> 
 
     The right button <em>does</em> work (opens the picker and stays open).<br /> 
 
     And it's all down to <code>$event.stopPropagation();</code> - funny huh?</code> 
 
     </p> 
 
     <ul> 
 
     <li ng-repeat="open in vm.opens">{{open}}</li> 
 
     </ul> 
 
    </div> 
 
    </body> 
 

 
</html>

并有一个博客这个问题,也是 http://blog.johnnyreilly.com/2015/05/angular-ui-bootstrap-datepicker-weirdness.html

将尝试找出什么在你的代码中的问题正是,你的时间可以有看看它。

EDIT1

你为什么不使用默认类型= “日期” 像

<input type="date" ng-model="date" value="{{ date | date: 'yyyy/MM/dd' }}" /> 
<br />{{ date | date: 'dd/MM/yyyy' }} 

EDIT2

OK想你的代码,拿出了只有日期相关的部分,它工作正常。

所以在你的代码中一定有其他东西在引起这个。 这里是我试过的代码,如果有帮助

angular.module('ui.bootstrap.demo', ['ngAnimate']); 
 
angular.module('ui.bootstrap.demo').controller('DatepickerDemoCtrl', function($scope,$filter) { 
 
    $scope.dateOptions = { 
 
     format: 'dd/mm/yyyy', 
 
     autoclose: false, 
 
     clearBtn: true, 
 
     // container: '#datepicker', 
 
     showOnFocus: true, 
 
     startDate: new Date(), 
 
     todayBtn: true, 
 
     todayHighlight: true, 
 
     weekStart: 1, 
 
     zIndexOffset: 5000 
 
    } 
 
}); 
 

 
angular.module('ui.bootstrap.demo').directive('bDatepicker', function() { 
 
    return { 
 
     require: '?ngModel', 
 
     restrict: 'A', 
 
     link: function($scope, element, attrs, controller) { 
 
      var updateModel, onblur; 
 

 
      if (controller != null) { 
 

 
       updateModel = function(event) { 
 
        console.log($scope.dateObject); 
 
        element.datepicker('hide'); 
 
        element.blur(); 
 
       }; 
 

 
       onblur = function() { 
 
        //we'll update the model in the blur() handler 
 
        //because it's possible the user put in an invalid date 
 
        //in the input box directly. 
 
        //Bootstrap datepicker will have overwritten invalid values 
 
        //on blur with today's date so we'll stick that in the model. 
 
        //this assumes that the forceParse option has been left as default(true) 
 
        //https://github.com/eternicode/bootstrap-datepicker#forceparse 
 
        var date = element.val(); 
 
        return $scope.$apply(function() { 
 
         return controller.$setViewValue(date); 
 
        }); 
 
       }; 
 

 
       controller.$render = function() { 
 
        var date = controller.$viewValue; 
 
        if (angular.isDefined(date) && date != null && angular.isDate(date)) { 
 
         // element.datepicker().data().datepicker.date = date; 
 
         element.datepicker('update', date); 
 
         element.datepicker('setValue'); 
 
         element.datepicker('update'); 
 
        } else if (angular.isDefined(date)) { 
 
         throw new Error('ng-Model value must be a Date object - currently it is a ' + typeof date + ' - use ui-date-format to convert it from a string'); 
 
        } 
 
        return controller.$viewValue; 
 
       }; 
 
      } 
 
      return attrs.$observe('bDatepicker', function(value) { 
 
       var options; 
 
       options = {}; //<--- insert your own defaults here! 
 
       if (angular.isObject(value)) { 
 
        options = value; 
 
       } 
 
       if (typeof(value) === "string" && value.length > 0) { 
 
        options = angular.fromJson(value); 
 
       } 
 
       return element.datepicker(options).on('changeDate', updateModel).on('blur', onblur); 
 
      }) 
 
     } 
 
    } 
 
});
<!doctype html> 
 
<html ng-app="ui.bootstrap.demo"> 
 

 
<head> 
 
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script> 
 
    <script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.5.0/js/bootstrap-datepicker.min.js"></script> 
 
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.js"></script> 
 
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular-animate.js"></script> 
 
    <script src="example.js"></script> 
 
    <!-- <link href="https://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet"> --> 
 
    <link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.5.0/css/bootstrap-datepicker.standalone.min.css" rel="stylesheet"> 
 
</head> 
 

 
<body ng-controller="DatepickerDemoCtrl"> 
 
    <input b-datepicker="{{dateOptions}}" ng-model="dateObject" id="datepicker" > 
 
    </br> 
 
    Date: {{dateObject}} 
 
</body> 
 

 
</html>

如果你可以提供一些混帐回购或工作普拉克/拨弄我可以找出究竟是什么错。但目前这是我所拥有的。希望它有帮助

+0

我将此标记为答案,因为它可以立即解决日期选择器打开/关闭的问题。我的老板现在决定采用更简单的实施方式(日/月/年下拉),所以我没有机会回去彻底测试解决方案,但是根据我在博客文章和Plunck中看到的内容,我认为这将足以让我下次在这个问题上得到解决(这可能很快)。谢谢! – ACIDSTEALTH

+0

@ACIDSTEALTH在回答这个问题时偶然发现了http://amsul.ca/pickadate.js/date/或https://github.com/alongubkin/angular-datepicker(两者都一样)我喜欢它是用户界面,没有用过这但用户界面不错 –

+0

那些都显得很不舒服。比Bootstrap风格好得多。 – ACIDSTEALTH