-
-
Save cgmartin/3daa01f910601ced9cd3 to your computer and use it in GitHub Desktop.
/** | |
* Decorates the ui-bootstrap datepicker directive's controller to allow | |
* refreshing the datepicker view (and rerunning invalid dates function) | |
* upon an event trigger: `$scope.$broadcast('refreshDatepickers');` | |
* | |
* Works with inline and popup. Include this after `ui.bootstrap` js | |
*/ | |
angular.module('ui.bootstrap.datepicker') | |
.config(function($provide) { | |
$provide.decorator('datepickerDirective', function($delegate) { | |
var directive = $delegate[0]; | |
var link = directive.link; | |
directive.compile = function() { | |
return function(scope, element, attrs, ctrls) { | |
link.apply(this, arguments); | |
var datepickerCtrl = ctrls[0]; | |
var ngModelCtrl = ctrls[1]; | |
if (ngModelCtrl) { | |
// Listen for 'refreshDatepickers' event... | |
scope.$on('refreshDatepickers', function refreshView() { | |
datepickerCtrl.refreshView(); | |
}); | |
} | |
} | |
}; | |
return $delegate; | |
}); | |
}); |
I want to stop scrolling calendra to go next month and next year. In short, I want to disable arrows(move) and toggling in calendar header. I tried to decorate using below code
angular.module('ui.bootstrap.datepicker') .config(function($provide) { $provide.decorator('uibDatepickerDirective', function($delegate)
but getting error like Uncaught Error: [$injector:modulerr] Failed to instantiate module myApp due to: Error: [$injector:modulerr] Failed to instantiate module ui.bootstrap due to: Error: [$injector:modulerr] Failed to instantiate module ui.bootstrap.datepicker due to: Error: [$injector:unpr] Unknown provider: uibDatepickerDirectiveProvider
it looks like injection error.
This was very helpful and worked perfectly for me! Thank you very much.
@extropianer
Did you ever find a none-flicker-solution to this issue? :)
@spirau or anyone else using uib-datepicker and dynamic-locale ....
did you manage to get the uib-datepicker day names to also refresh?
This works for me and doesn't flicker:
super hacky but this seems to work for me. Replace the function in datepicker. I tried using $timeout but it didn't like it.
Step 1. Change the signature to include a retry
variable. Its just a placeholder to kill the infinite loop.
this.refreshView = function(retry) {
Step 2. Add this to the end of the function
if(!retry){
setTimeout(function () {
console.log("Refreshing view timeout");
_this.refreshView(true);
$scope.$apply();
}, 1);
}
Full Code:
this.refreshView = function(retry) {
console.log("Refresh view");
if (this.element) {
$scope.selectedDt = null;
this._refreshView();
if ($scope.activeDt) {
$scope.activeDateId = $scope.activeDt.uid;
}
var date = ngModelCtrl.$viewValue ? new Date(ngModelCtrl.$viewValue) : null;
date = dateParser.fromTimezone(date, ngModelOptions.timezone);
ngModelCtrl.$setValidity('dateDisabled', !date ||
this.element && !this.isDisabled(date));
}
var _this = this;
if(!retry){
setTimeout(function () {
console.log("Refreshing view timeout");
_this.refreshView(true);
$scope.$apply();
}, 1);
}
};
I suppose that the cause of the problem here is the one-time binding (ng-repeat="label in ::labels track by $index"
).
So that the day names get refreshed only when the ng-switch-when
condition gets changed, as @spirau mentioned. So, the ugly workaround would be to force this change automatically:
scope.$on('$localeChangeSuccess', function () {
const mode = scope.datepickerMode;
scope.datepickerMode = '';
scope.$$postDigest(() => {
scope.datepickerMode = mode;
});
datepickerCtrl.refreshView();
});
It will flicker when opened, though, but that's not critical for me. The datepicker is always closed when the locale gets changed.
If anyone else figured out a better solution please let us know!
Cheers.
If you're using a later version of Angular UI Bootstrap, replace:
$provide.decorator('datepickerDirective', function($delegate) {
with
$provide.decorator('uibDatepickerDirective', function($delegate) {
Using version 0.14.2, you need to change "datepickerDirective" to "uibDatepickerDirective".
I wanted to update the datepicker on locale change using dynamic-locale. So I directly connected the datepicker refresh to the $localeChnageSuccess event. That's working but only for the month name. The labels for the days are well defined in the new language in the datePicker array due to the forced refreshView, but not refreshed by angular itself.
Even when playing manually with the datepicker the day names dont't change. The new day names only appear if I go to a month view then back to the day view. Where is the binding!
Any idea how to fix it?