-
-
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; | |
}); | |
}); |
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) {
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.