Unverified Commit 4a7f2f0e authored by Dmitriy Shekhovtsov's avatar Dmitriy Shekhovtsov Committed by GitHub
Browse files

feat(datepicker): added BsLocaleService to change datepicker locale (#3209)

* feat(datepicker): added BsLocaleService to change datepicker locale

* chore(datepicker): removed obsolete comments

* fix(datepicker): add BsLocaleService to exports

* demo(datepicker): change locale demo according to BsLocaleService
parent 735101c5
Showing with 100 additions and 35 deletions
+100 -35
......@@ -70,11 +70,11 @@ export const demoComponentContent: ContentSection[] = [
component: require('!!raw-loader?lang=typescript!./demos/change-locale/change-locale.ts'),
html: require('!!raw-loader?lang=markup!./demos/change-locale/change-locale.html'),
description: `
<p>Datepicker can use different locales. <br>It's possible to change a locale by changing
<code>locale</code>
property in <code>bsConfig</code> object, list of available locales is in dropdown below.</p>
<p>To use a different locale, you have to import it from <code>ngx-bootstrap/bs-moment</code> and define it
in your <code>@NgModule</code> using function <code>defineLocale</code></p>
<p>Datepicker can use different locales. <br>It's possible to change a locale by calling
<code>use</code>
method of <code>BsLocaleService</code>, list of available locales is in dropdown below.</p>
<p>To use a different locale, you have to import it from <code>ngx-bootstrap/bs-moment</code> first, then
define it in your <code>@NgModule</code> using function <code>defineLocale</code></p>
<p>Example: </p>
<code>import { defineLocale } from 'ngx-bootstrap/bs-moment';</code><br>
<code>import { de } from 'ngx-bootstrap/locale';</code><br>
......
......@@ -7,7 +7,7 @@
</select>
</div>
<div class="col-xs-6 col-6 col-md-4 col-lg-3 form-group">
<input placeholder="Datepicker" type="text" class="form-control" bsDatepicker #dp="bsDatepicker" [bsConfig]="bsConfig">
<input placeholder="Datepicker" type="text" class="form-control" bsDatepicker #dp="bsDatepicker">
</div>
<div class="col-xs-12 col-12 col-md-4 col-lg-4 form-group">
<input type="button"
......@@ -27,7 +27,7 @@
</select>
</div>
<div class="col-xs-6 col-6 col-md-4 col-lg-3 form-group">
<input placeholder="Daterangepicker" type="text" class="form-control" bsDaterangepicker #dpr="bsDaterangepicker" [bsConfig]="bsConfig">
<input placeholder="Daterangepicker" type="text" class="form-control" bsDaterangepicker #dpr="bsDaterangepicker">
</div>
<div class="col-xs-12 col-12 col-md-4 col-lg-4 form-group">
<input type="button"
......
import { Component } from '@angular/core';
import { BsDatepickerConfig } from 'ngx-bootstrap/datepicker';
import { BsDatepickerConfig, BsLocaleService } from 'ngx-bootstrap/datepicker';
import { listLocales } from 'ngx-bootstrap/bs-moment';
@Component({
......@@ -9,15 +9,13 @@ import { listLocales } from 'ngx-bootstrap/bs-moment';
export class DemoDatepickerChangeLocaleComponent {
locale = 'en';
locales = listLocales();
bsConfig: Partial<BsDatepickerConfig>;
constructor(private _localeService: BsLocaleService) {
}
applyLocale(pop: any) {
// create new object on each property change
// so Angular can catch object reference change
this.bsConfig = Object.assign({}, { locale: this.locale });
setTimeout(() => {
pop.hide();
pop.show();
});
this._localeService.use(this.locale);
pop.hide();
pop.show();
}
}
......@@ -3,6 +3,7 @@ import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { BsDatepickerDirective } from './bs-datepicker.component';
import { formatDate } from '../bs-moment/format';
import { getLocale } from '../bs-moment/locale/locales.service';
import { BsLocaleService } from './bs-locale.service';
const BS_DATEPICKER_VALUE_ACCESSOR = {
provide: NG_VALUE_ACCESSOR,
......@@ -27,9 +28,11 @@ export class BsDatepickerInputDirective
private _value: Date;
constructor(@Host() private _picker: BsDatepickerDirective,
private _localeService: BsLocaleService,
private _renderer: Renderer2,
private _elRef: ElementRef,
private changeDetection: ChangeDetectorRef) {
// update input value on datepicker value update
this._picker.bsValueChange.subscribe((value: Date) => {
this._setInputValue(value);
if (this._value !== value) {
......@@ -39,13 +42,18 @@ export class BsDatepickerInputDirective
}
this.changeDetection.markForCheck();
});
// update input value on locale change
this._localeService.localeChange.subscribe(() => {
this._setInputValue(this._value);
});
}
_setInputValue(value: Date): void {
const initialDate = formatDate(
value,
this._picker._config.dateInputFormat,
this._picker._config.locale
this._localeService.currentLocale
) || '';
this._renderer.setProperty(this._elRef.nativeElement, 'value', initialDate);
}
......@@ -60,11 +68,11 @@ export class BsDatepickerInputDirective
if (!value) {
this._value = null;
}
const _locale = getLocale(this._picker._config.locale);
const _localeKey = this._localeService.currentLocale;
const _locale = getLocale(_localeKey);
if (!_locale) {
throw new Error(
`Locale "${this._picker._config
.locale}" is not defined, please add it with "defineLocale(...)"`
`Locale "${_localeKey}" is not defined, please add it with "defineLocale(...)"`
);
}
if (typeof value === 'string') {
......
......@@ -8,6 +8,7 @@ import { BsDatepickerContainerComponent } from './themes/bs/bs-datepicker-contai
import { Subscription } from 'rxjs/Subscription';
import 'rxjs/add/operator/filter';
import { BsDatepickerConfig } from './bs-datepicker.config';
import { BsLocaleService } from './bs-locale.service';
@Directive({
selector: '[bsDatepicker]',
......
......@@ -6,7 +6,7 @@ import {
@Injectable()
export class BsDatepickerConfig
implements DatepickerRenderOptions, DatepickerFormatOptions {
implements DatepickerRenderOptions {
value?: Date | Date[];
isDisabled?: boolean;
/**
......@@ -36,11 +36,6 @@ export class BsDatepickerConfig
rangeInputFormat = 'L';
// DatepickerFormatOptions
/**
* Allows to globally set default locale of datepicker,
* see documentation on how to enable custom locales
*/
locale = 'en';
monthTitle = 'MMMM';
yearTitle = 'YYYY';
dayLabel = 'D';
......
......@@ -22,6 +22,8 @@ import { BsCalendarLayoutComponent } from './themes/bs/bs-calendar-layout.compon
import { BsDatepickerInputDirective } from './bs-datepicker-input.directive';
import { BsDaterangepickerInputDirective } from './bs-daterangepicker-input.directive';
import { BsLocaleService } from './bs-locale.service';
import { warnOnce } from '../utils/warn-once';
const _exports = [
......@@ -74,7 +76,8 @@ export class BsDatepickerModule {
BsDatepickerStore,
BsDatepickerActions,
BsDatepickerConfig,
BsDatepickerEffects
BsDatepickerEffects,
BsLocaleService
]
};
}
......
......@@ -3,6 +3,7 @@ import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { formatDate } from '../bs-moment/format';
import { getLocale } from '../bs-moment/locale/locales.service';
import { BsDaterangepickerDirective } from './bs-daterangepicker.component';
import { BsLocaleService } from './bs-locale.service';
const BS_DATERANGEPICKER_VALUE_ACCESSOR = {
provide: NG_VALUE_ACCESSOR,
......@@ -27,9 +28,11 @@ export class BsDaterangepickerInputDirective
private _value: Date[];
constructor(@Host() private _picker: BsDaterangepickerDirective,
private _localeService: BsLocaleService,
private _renderer: Renderer2,
private _elRef: ElementRef,
private changeDetection: ChangeDetectorRef) {
// update input value on datepicker value update
this._picker.bsValueChange.subscribe((value: Date[]) => {
this._setInputValue(value);
if (this._value !== value) {
......@@ -39,6 +42,11 @@ export class BsDaterangepickerInputDirective
}
this.changeDetection.markForCheck();
});
// update input value on locale change
this._localeService.localeChange.subscribe(() => {
this._setInputValue(this._value);
});
}
_setInputValue(date: Date[]): void {
......@@ -47,12 +55,12 @@ export class BsDaterangepickerInputDirective
const start = formatDate(
date[0],
this._picker._config.rangeInputFormat,
this._picker._config.locale
this._localeService.currentLocale
) || '';
const end = formatDate(
date[1],
this._picker._config.rangeInputFormat,
this._picker._config.locale
this._localeService.currentLocale
) || '';
range = (start && end) ? start + this._picker._config.rangeSeparator + end : '';
}
......@@ -70,11 +78,11 @@ export class BsDaterangepickerInputDirective
this._value = null;
}
const _locale = getLocale(this._picker._config.locale);
const _localeKey = this._localeService.currentLocale;
const _locale = getLocale(_localeKey);
if (!_locale) {
throw new Error(
`Locale "${this._picker._config
.locale}" is not defined, please add it with "defineLocale(...)"`
`Locale "${_localeKey}" is not defined, please add it with "defineLocale(...)"`
);
}
......
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
@Injectable()
export class BsLocaleService {
private _defaultLocale = 'en';
private _locale = new BehaviorSubject<string>(this._defaultLocale);
private _localeChange: Observable<string> = this._locale.asObservable();
get locale(): BehaviorSubject<string> {
return this._locale;
}
get localeChange(): Observable<string> {
return this._localeChange;
}
get currentLocale(): string {
return this._locale.getValue();
}
use(locale: string): void {
if (locale === this.currentLocale) {
return;
}
this._locale.next(locale);
}
}
......@@ -10,3 +10,4 @@ export { BsDatepickerModule } from './bs-datepicker.module';
export { BsDatepickerDirective } from './bs-datepicker.component';
export { BsDaterangepickerDirective } from './bs-daterangepicker.component';
export { BsDatepickerConfig } from './bs-datepicker.config';
export { BsLocaleService } from './bs-locale.service';
......@@ -24,6 +24,8 @@ export class BsDatepickerActions {
static readonly SET_MAX_DATE = '[datepicker] set max date';
static readonly SET_IS_DISABLED = '[datepicker] set is disabled';
static readonly SET_LOCALE = '[datepicker] set datepicker locale';
static readonly SELECT_RANGE = '[daterangepicker] select dates range';
calculate(): Action {
......@@ -108,4 +110,11 @@ export class BsDatepickerActions {
payload: value
};
}
setLocale(locale: string): Action {
return {
type: BsDatepickerActions.SET_LOCALE,
payload: locale
};
}
}
......@@ -19,6 +19,7 @@ import {
import { BsDatepickerActions } from './bs-datepicker.actions';
import { BsDatepickerStore } from './bs-datepicker.store';
import { Subscription } from 'rxjs/Subscription';
import { BsLocaleService } from '../bs-locale.service';
@Injectable()
export class BsDatepickerEffects {
......@@ -31,7 +32,8 @@ export class BsDatepickerEffects {
private _store: BsDatepickerStore;
private _subs: Subscription[] = [];
constructor(private _actions: BsDatepickerActions) {}
constructor(private _actions: BsDatepickerActions,
private _localeService: BsLocaleService) {}
init(_bsDatepickerStore: BsDatepickerStore): BsDatepickerEffects {
this._store = _bsDatepickerStore;
......@@ -69,7 +71,8 @@ export class BsDatepickerEffects {
/* Set rendering options */
setOptions(_config: BsDatepickerConfig): BsDatepickerEffects {
this._store.dispatch(this._actions.setOptions(_config));
const _options = Object.assign({locale: this._localeService.currentLocale}, _config);
this._store.dispatch(this._actions.setOptions(_options));
return this;
}
......@@ -224,6 +227,12 @@ export class BsDatepickerEffects {
.subscribe(hoveredDate => this._store.dispatch(this._actions.flag()))
);
// on locale change
this._subs.push(
this._localeService.localeChange
.subscribe(locale => this._store.dispatch(this._actions.setLocale(locale)))
)
return this;
}
......
......@@ -73,6 +73,7 @@ const _initialView: BsDatepickerViewState = { date: new Date(), mode: 'day' };
export const initialDatepickerState: BsDatepickerState = Object.assign(
new BsDatepickerConfig(),
{
locale: 'en',
view: _initialView,
selectedRange: [],
monthViewOptions: defaultMonthOptions
......
......@@ -7,6 +7,7 @@ import { BsDatepickerActions } from '../../reducer/bs-datepicker.actions';
import { BsDatepickerEffects } from '../../reducer/bs-datepicker.effects';
import { BsDatepickerStore } from '../../reducer/bs-datepicker.store';
import { Subscription } from 'rxjs/Subscription';
import { BsLocaleService } from '../../bs-locale.service';
@Component({
selector: 'bs-datepicker-container',
......
......@@ -52,7 +52,8 @@ export {
MonthPickerComponent,
YearPickerComponent,
BsDatepickerModule,
BsDatepickerConfig
BsDatepickerConfig,
BsLocaleService
} from './datepicker';
export {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment