Skip to content

Commit eab5004

Browse files
committedJun 23, 2023
feat: Supports ngModel and formControlName
1 parent 6595681 commit eab5004

File tree

3 files changed

+78
-19
lines changed

3 files changed

+78
-19
lines changed
 

‎projects/ngx-laydate/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "ngx-laydate",
3-
"version": "13.0.0",
3+
"version": "13.0.1",
44
"author": "lanxuexing",
55
"license": "MIT",
66
"keywords": [

‎projects/ngx-laydate/src/lib/ngx-laydate.directive.ts

+71-13
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,13 @@ import {
1010
OnChanges,
1111
OnDestroy,
1212
Output,
13-
SimpleChanges
13+
SimpleChanges,
14+
forwardRef
1415
} from '@angular/core';
1516
import { ChangeFilter } from './change-filter';
1617
import { normalizeCommonJSImport } from './utils';
18+
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
19+
import { Subject, takeUntil } from 'rxjs';
1720

1821
export interface NgxLaydateConfig {
1922
laydate: any | (() => Promise<any>);
@@ -22,12 +25,19 @@ export interface NgxLaydateConfig {
2225

2326
export const NGX_LAYDATE_CONFIG = new InjectionToken<NgxLaydateConfig>('NGX_LAYDATE_CONFIG');
2427

28+
const NGX_LAYDATE_VALUE_ACCESSOR = {
29+
provide: NG_VALUE_ACCESSOR,
30+
useExisting: forwardRef(() => NgxLaydateDirective),
31+
multi: true
32+
};
33+
2534
@Directive({
2635
selector: 'laydate, [laydate]',
27-
exportAs: 'laydate'
36+
exportAs: 'laydate',
37+
providers: [NGX_LAYDATE_VALUE_ACCESSOR]
2838
})
29-
export class NgxLaydateDirective implements OnChanges, OnDestroy, AfterViewInit {
30-
@Input() options: any;
39+
export class NgxLaydateDirective implements OnChanges, OnDestroy, AfterViewInit, ControlValueAccessor {
40+
@Input() options: Partial<any> = {};
3141

3242
// ngx-laydate events
3343
@Output() laydateInit = new EventEmitter<any>();
@@ -44,6 +54,14 @@ export class NgxLaydateDirective implements OnChanges, OnDestroy, AfterViewInit
4454
private laydateIns: any;
4555
private initLaydateTimer?: number;
4656

57+
// controlValueAccessor
58+
private isNgModel = false;
59+
private currentValue = '';
60+
private destroy$ = new Subject<void>();
61+
private ngLaydateCreated$ = new Subject<void>();
62+
private onChange: any = () => { };
63+
private onTouched: any = () => { };
64+
4765
constructor(
4866
@Inject(NGX_LAYDATE_CONFIG) public config: NgxLaydateConfig,
4967
private el: ElementRef,
@@ -60,10 +78,38 @@ export class NgxLaydateDirective implements OnChanges, OnDestroy, AfterViewInit
6078
ngOnDestroy() {
6179
window.clearTimeout(this.initLaydateTimer);
6280
this.dispose();
81+
this.destroy$.next();
82+
this.destroy$.complete();
6383
}
6484

6585
ngAfterViewInit(): void {
66-
this.initLaydateTimer = window.setTimeout(() => this.initChart());
86+
this.initLaydateTimer = window.setTimeout(() => this.initLaydate());
87+
}
88+
89+
writeValue(obj: any): void {
90+
this.currentValue = obj;
91+
}
92+
93+
registerOnChange(fn: any): void {
94+
this.isNgModel = true;
95+
this.onChange = fn;
96+
// delay execution until ngLaydate instance is created.
97+
this.ngLaydateCreated$.asObservable().pipe(
98+
takeUntil(this.destroy$)
99+
).subscribe(() => {
100+
this.setOption({ ...this.options, value: this.currentValue });
101+
});
102+
}
103+
104+
registerOnTouched(fn: any): void {
105+
this.onTouched = fn;
106+
}
107+
108+
setDisabledState?(isDisabled: boolean): void {
109+
const dom = this.el.nativeElement;
110+
if (dom && dom.nodeName === 'INPUT') {
111+
dom.disabled = isDisabled;
112+
}
67113
}
68114

69115
public hint(value: string) {
@@ -100,7 +146,7 @@ export class NgxLaydateDirective implements OnChanges, OnDestroy, AfterViewInit
100146
}
101147

102148
private createLaydate() {
103-
const dom = this.el.nativeElement;
149+
const dom = (this.options && this.options.elem) || this.el.nativeElement;
104150

105151
// here a bit tricky: we check if the laydate module is provided as function returning native import('...') then use the promise
106152
// otherwise create the function that imitates behaviour above with a provided as is module
@@ -109,27 +155,39 @@ export class NgxLaydateDirective implements OnChanges, OnDestroy, AfterViewInit
109155
typeof this.laydate === 'function' ? this.laydate : () => Promise.resolve(this.laydate);
110156

111157
return normalizeCommonJSImport(load()).then((laydateInstance: any) => {
112-
this.options = Object.assign({}, this.options, { elem: dom });
158+
this.options = Object.assign({}, this.options, {
159+
elem: dom,
160+
...(this.isNgModel && {
161+
// intercept 'done' callback of the control, continue event propagation when callback is present.
162+
...(this.options && this.options.done && { ngDone: this.options.done }),
163+
done: (value, date, endDate) => {
164+
this.onChange(value);
165+
if (this.options && this.options.ngDone) {
166+
this.options.ngDone(value, date, endDate);
167+
}
168+
}
169+
})
170+
});
113171
return laydateInstance;
114172
});
115173
});
116174
}
117175

118-
private async initChart() {
176+
private async initLaydate() {
119177
await this.onOptionsChange(this.options);
120178
}
121179

122180
private async onOptionsChange(opt: any) {
123-
// if (!opt) {
124-
// return;
125-
// }
126-
127181
if (this.ngLaydate) {
128182
this.setOption(this.options);
129183
} else {
130184
this.ngLaydate = await this.createLaydate();
131185
this.laydateInit.emit(this.ngLaydate);
132-
this.setOption(this.options);
186+
if (this.isNgModel) {
187+
this.ngLaydateCreated$.next();
188+
} else {
189+
this.setOption(this.options);
190+
}
133191
}
134192
}
135193

‎projects/ngx-laydate/src/lib/ngx-laydate.module.ts

+6-5
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import { ModuleWithProviders, NgModule } from '@angular/core';
2-
import { NgxLaydateConfig, NgxLaydateDirective, NGX_LAYDATE_CONFIG } from './ngx-laydate.directive';
2+
import { FormsModule } from '@angular/forms';
3+
import { NGX_LAYDATE_CONFIG, NgxLaydateConfig, NgxLaydateDirective } from './ngx-laydate.directive';
34

45
@NgModule({
5-
imports: [],
6-
declarations: [ NgxLaydateDirective],
7-
exports: [ NgxLaydateDirective]
6+
imports: [FormsModule],
7+
declarations: [NgxLaydateDirective],
8+
exports: [NgxLaydateDirective]
89
})
910
export class NgxLaydateModule {
1011
static forRoot(config?: NgxLaydateConfig): ModuleWithProviders<NgxLaydateModule> {
@@ -20,4 +21,4 @@ export class NgxLaydateModule {
2021
}
2122
}
2223

23-
export { NgxLaydateDirective, NGX_LAYDATE_CONFIG };
24+
export { NGX_LAYDATE_CONFIG, NgxLaydateDirective };

0 commit comments

Comments
 (0)
Please sign in to comment.