UNPKG

8.83 kBJavaScriptView Raw
1import { Directive, ElementRef, EventEmitter, Input, Output, Renderer2, ViewContainerRef } from '@angular/core';
2import { ComponentLoaderFactory } from 'ngx-bootstrap/component-loader';
3import { BehaviorSubject, Subject } from 'rxjs';
4import { filter, takeUntil } from 'rxjs/operators';
5import { BsDatepickerConfig } from './bs-datepicker.config';
6import { BsDatepickerContainerComponent } from './themes/bs/bs-datepicker-container.component';
7import { checkBsValue } from './utils/bs-calendar-utils';
8export class BsDatepickerDirective {
9 constructor(_config, _elementRef, _renderer, _viewContainerRef, cis) {
10 this._config = _config;
11 this._elementRef = _elementRef;
12 this._renderer = _renderer;
13 /**
14 * Placement of a datepicker. Accepts: "top", "bottom", "left", "right"
15 */
16 this.placement = 'bottom';
17 /**
18 * Specifies events that should trigger. Supports a space separated list of
19 * event names.
20 */
21 this.triggers = 'click';
22 /**
23 * Close datepicker on outside click
24 */
25 this.outsideClick = true;
26 /**
27 * A selector specifying the element the datepicker should be appended to.
28 */
29 this.container = 'body';
30 this.outsideEsc = true;
31 this.isDestroy$ = new Subject();
32 /**
33 * Indicates whether datepicker's content is enabled or not
34 */
35 this.isDisabled = false;
36 /**
37 * Emits when datepicker value has been changed
38 */
39 this.bsValueChange = new EventEmitter();
40 this._subs = [];
41 this._dateInputFormat$ = new Subject();
42 // todo: assign only subset of fields
43 Object.assign(this, this._config);
44 this._datepicker = cis.createLoader(_elementRef, _viewContainerRef, _renderer);
45 this.onShown = this._datepicker.onShown;
46 this.onHidden = this._datepicker.onHidden;
47 this.isOpen$ = new BehaviorSubject(this.isOpen);
48 }
49 /**
50 * Returns whether or not the datepicker is currently being shown
51 */
52 get isOpen() {
53 return this._datepicker.isShown;
54 }
55 set isOpen(value) {
56 this.isOpen$.next(value);
57 }
58 /**
59 * Initial value of datepicker
60 */
61 set bsValue(value) {
62 if (this._bsValue && value && this._bsValue.getTime() === value.getTime()) {
63 return;
64 }
65 if (!this._bsValue && value) {
66 const now = new Date();
67 value.setMilliseconds(now.getMilliseconds());
68 value.setSeconds(now.getSeconds());
69 value.setMinutes(now.getMinutes());
70 value.setHours(now.getHours());
71 }
72 this._bsValue = value;
73 this.bsValueChange.emit(value);
74 }
75 get dateInputFormat$() {
76 return this._dateInputFormat$;
77 }
78 get bsConfig() {
79 return this._bsConfig;
80 }
81 /**
82 * Config object for datepicker
83 */
84 set bsConfig(bsConfig) {
85 this._bsConfig = bsConfig;
86 this.setConfig();
87 this._dateInputFormat$.next(bsConfig && bsConfig.dateInputFormat);
88 }
89 ngOnInit() {
90 this._datepicker.listen({
91 outsideClick: this.outsideClick,
92 outsideEsc: this.outsideEsc,
93 triggers: this.triggers,
94 show: () => this.show()
95 });
96 this.setConfig();
97 }
98 ngOnChanges(changes) {
99 if (!this._datepickerRef || !this._datepickerRef.instance) {
100 return;
101 }
102 if (changes.minDate) {
103 this._datepickerRef.instance.minDate = this.minDate;
104 }
105 if (changes.maxDate) {
106 this._datepickerRef.instance.maxDate = this.maxDate;
107 }
108 if (changes.daysDisabled) {
109 this._datepickerRef.instance.daysDisabled = this.daysDisabled;
110 }
111 if (changes.datesDisabled) {
112 this._datepickerRef.instance.datesDisabled = this.datesDisabled;
113 }
114 if (changes.datesEnabled) {
115 this._datepickerRef.instance.datesEnabled = this.datesEnabled;
116 }
117 if (changes.isDisabled) {
118 this._datepickerRef.instance.isDisabled = this.isDisabled;
119 }
120 if (changes.dateCustomClasses) {
121 this._datepickerRef.instance.dateCustomClasses = this.dateCustomClasses;
122 }
123 if (changes.dateTooltipTexts) {
124 this._datepickerRef.instance.dateTooltipTexts = this.dateTooltipTexts;
125 }
126 }
127 ngAfterViewInit() {
128 this.isOpen$.pipe(filter(isOpen => isOpen !== this.isOpen), takeUntil(this.isDestroy$))
129 .subscribe(() => this.toggle());
130 }
131 /**
132 * Opens an element’s datepicker. This is considered a “manual” triggering of
133 * the datepicker.
134 */
135 show() {
136 if (this._datepicker.isShown) {
137 return;
138 }
139 this.setConfig();
140 this._datepickerRef = this._datepicker
141 .provide({ provide: BsDatepickerConfig, useValue: this._config })
142 .attach(BsDatepickerContainerComponent)
143 .to(this.container)
144 .position({ attachment: this.placement })
145 .show({ placement: this.placement });
146 // if date changes from external source (model -> view)
147 this._subs.push(this.bsValueChange.subscribe((value) => {
148 if (this._datepickerRef) {
149 this._datepickerRef.instance.value = value;
150 }
151 }));
152 // if date changes from picker (view -> model)
153 if (this._datepickerRef) {
154 this._subs.push(this._datepickerRef.instance.valueChange.subscribe((value) => {
155 this.bsValue = value;
156 this.hide();
157 }));
158 }
159 }
160 /**
161 * Closes an element’s datepicker. This is considered a “manual” triggering of
162 * the datepicker.
163 */
164 hide() {
165 if (this.isOpen) {
166 this._datepicker.hide();
167 }
168 for (const sub of this._subs) {
169 sub.unsubscribe();
170 }
171 if (this._config.returnFocusToInput) {
172 this._renderer.selectRootElement(this._elementRef.nativeElement).focus();
173 }
174 }
175 /**
176 * Toggles an element’s datepicker. This is considered a “manual” triggering
177 * of the datepicker.
178 */
179 toggle() {
180 if (this.isOpen) {
181 return this.hide();
182 }
183 this.show();
184 }
185 /**
186 * Set config for datepicker
187 */
188 setConfig() {
189 this._config = Object.assign({}, this._config, this.bsConfig, {
190 value: checkBsValue(this._bsValue, this.maxDate || this.bsConfig && this.bsConfig.maxDate),
191 isDisabled: this.isDisabled,
192 minDate: this.minDate || this.bsConfig && this.bsConfig.minDate,
193 maxDate: this.maxDate || this.bsConfig && this.bsConfig.maxDate,
194 daysDisabled: this.daysDisabled || this.bsConfig && this.bsConfig.daysDisabled,
195 dateCustomClasses: this.dateCustomClasses || this.bsConfig && this.bsConfig.dateCustomClasses,
196 dateTooltipTexts: this.dateTooltipTexts || this.bsConfig && this.bsConfig.dateTooltipTexts,
197 datesDisabled: this.datesDisabled || this.bsConfig && this.bsConfig.datesDisabled,
198 datesEnabled: this.datesEnabled || this.bsConfig && this.bsConfig.datesEnabled,
199 minMode: this.minMode || this.bsConfig && this.bsConfig.minMode
200 });
201 }
202 ngOnDestroy() {
203 this._datepicker.dispose();
204 this.isOpen$.next(false);
205 if (this.isDestroy$) {
206 this.isDestroy$.next();
207 this.isDestroy$.complete();
208 }
209 }
210}
211BsDatepickerDirective.decorators = [
212 { type: Directive, args: [{
213 selector: '[bsDatepicker]',
214 exportAs: 'bsDatepicker'
215 },] }
216];
217BsDatepickerDirective.ctorParameters = () => [
218 { type: BsDatepickerConfig },
219 { type: ElementRef },
220 { type: Renderer2 },
221 { type: ViewContainerRef },
222 { type: ComponentLoaderFactory }
223];
224BsDatepickerDirective.propDecorators = {
225 placement: [{ type: Input }],
226 triggers: [{ type: Input }],
227 outsideClick: [{ type: Input }],
228 container: [{ type: Input }],
229 outsideEsc: [{ type: Input }],
230 onShown: [{ type: Output }],
231 onHidden: [{ type: Output }],
232 isDisabled: [{ type: Input }],
233 minDate: [{ type: Input }],
234 maxDate: [{ type: Input }],
235 minMode: [{ type: Input }],
236 daysDisabled: [{ type: Input }],
237 datesDisabled: [{ type: Input }],
238 datesEnabled: [{ type: Input }],
239 dateCustomClasses: [{ type: Input }],
240 dateTooltipTexts: [{ type: Input }],
241 bsValueChange: [{ type: Output }],
242 isOpen: [{ type: Input }],
243 bsValue: [{ type: Input }],
244 bsConfig: [{ type: Input }]
245};
246//# sourceMappingURL=bs-datepicker.component.js.map
\No newline at end of file