4

Я работаю над интеграцией Eternicode's Bootstrap Datepicker в свое приложение. Я не был уверен, как подключить его к моей модели, поэтому я нашел директиву, которая использует ее от here. Теперь у меня есть datepicker на моей странице, но он не останется открытым, когда я нажимаю на поле ввода. Датпикер открывается и закрывается почти мгновенно. Если я нажму на соседнее поле и вкладку в поле datepicker, он останется открытым, как и ожидалось. У меня также возникают проблемы с тем, чтобы он появился там, где я бы хотел. Когда он открывается, он находится под некоторыми другими элементами и неуместен. Он должен открываться непосредственно под полем ввода. См. Снимок экрана ниже.Угловая 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

Я создал скрипку, но я не могу заставить ее работать правильно. Я получаю сообщение об ошибке «Неудачная ошибка: [$ инжектор: modulerr]], что я не могу понять, как ее решить. Вот ссылка: https://jsfiddle.net/kxge3cqf/ – ACIDSTEALTH

+0

@ACIDSTEALTH Я скопировал код в локальном env и что '[$ injector: modulerr]' кажется из-за 'angular.module ('myApp', ['ui .bootstrap ']), здесь ui.bootstrap не был определен, после включения его из внешней ссылки, я снова получил 'невозможно загрузить файл: ///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

ок попробовал ваш код, взял только часть даты, связанные, Он работает нормально.

Так что в вашем коде должно быть что-то еще, что вызывает это. Вот код, который я попробовал, если это помогает

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 (оба) Мне нравится, что это ui, не использовали это, но ui было хорошо –

+0

Эти оба выглядят довольно больными. Намного лучше, чем стиль Bootstrap. – ACIDSTEALTH