99 ChangeDetectionStrategy ,
1010 forwardRef ,
1111 Injector ,
12- ViewChild
12+ ViewChild ,
13+ OnDestroy
1314} from '@angular/core' ;
1415import { NgControl , UntypedFormControl , ControlValueAccessor , NG_VALUE_ACCESSOR } from '@angular/forms' ;
1516import { dateValidator , hasRequiredValidator } from '../core/validator.functions' ;
@@ -58,9 +59,11 @@ export type Moment = _moment.Moment;
5859 [(ngModel)]="_value" [min]="min" [max]="max"
5960 [placeholder]="placeholder" [disabled]="disabled" [readonly]="readonly"
6061 (dateChange)="onDateChange($event)">
61- <mat-datepicker #datePicker [touchUi]="true" type="datetime">
62+ <mat-datepicker #datePicker [touchUi]="true" type="datetime" >
6263 <mat-datepicker-actions>
63- <plex-button class="btn-ok-fecha" matDatepickerApply type="info" size="sm" label="Aceptar"></plex-button>
64+ <plex-button class="btn-ok-fecha" matDatepickerApply type="info" size="sm" label="Aceptar"
65+ [disabled]="!hasDaySelected">
66+ </plex-button>
6467 </mat-datepicker-actions>
6568 </mat-datepicker>
6669 </ng-container>
@@ -134,11 +137,11 @@ export type Moment = _moment.Moment;
134137 ` ,
135138} )
136139
137- export class PlexDateTimeComponent implements AfterViewInit , OnChanges , ControlValueAccessor {
140+ export class PlexDateTimeComponent implements AfterViewInit , OnChanges , OnDestroy , ControlValueAccessor {
138141
139- @ViewChild ( MatDatepicker ) datePicker ?: MatDatepicker < Date > ;
140- @ViewChild ( NgxMatTimepickerComponent ) dateTimePicker ?: NgxMatTimepickerComponent ;
141- @ViewChild ( NgxMatTimepickerComponent ) timePicker ?: NgxMatTimepickerComponent ;
142+ @ViewChild ( 'datePicker' ) datePicker ?: MatDatepicker < Date > ;
143+ @ViewChild ( 'dateTimePicker' ) dateTimePicker ?: NgxMatTimepickerComponent ;
144+ @ViewChild ( 'timePicker' ) timePicker ?: NgxMatTimepickerComponent ;
142145
143146 private _min : Date | null = null ;
144147 private _max : Date | null = null ;
@@ -223,6 +226,7 @@ export class PlexDateTimeComponent implements AfterViewInit, OnChanges, ControlV
223226 private onTouched : ( ) => void = ( ) => { } ;
224227 private propagateChange : ( val : Date | null ) => void = ( ) => { } ;
225228 control ?: NgControl ;
229+ hasDaySelected = false ;
226230
227231 constructor (
228232 private element : ElementRef < HTMLElement > ,
@@ -238,6 +242,41 @@ export class PlexDateTimeComponent implements AfterViewInit, OnChanges, ControlV
238242 const input : HTMLInputElement | null = this . element . nativeElement ?. querySelector ( 'input[data-main]' ) ;
239243 input ?. focus ( ) ;
240244 }
245+
246+ this . datePicker ?. openedStream . subscribe ( ( ) => {
247+ // este bloque se usa para habilitar/deshabilitar el botón Aceptar del datepicker
248+ this . hasDaySelected = false ;
249+
250+ setTimeout ( ( ) => {
251+ const dpAny = this . datePicker as any ;
252+ const overlayEl : HTMLElement | null = dpAny ?. _overlayRef ?. overlayElement ?? null ;
253+ if ( ! overlayEl ) { return ; }
254+
255+ const handler = ( ev : MouseEvent ) => {
256+ const t = ev . target as HTMLElement | null ;
257+ if ( ! t ) { return ; }
258+
259+ // Si el click ocurrió en una celda de día del calendario => ya hay selección (o intento de selección)
260+ if ( t . closest ( '.mat-calendar-content .mat-calendar-body-cell' ) ) {
261+ this . hasDaySelected = true ;
262+ }
263+ } ;
264+
265+ overlayEl . addEventListener ( 'click' , handler , true ) ;
266+ this . removeClickListener = ( ) => overlayEl . removeEventListener ( 'click' , handler , true ) ;
267+ } , 0 ) ;
268+ } ) ;
269+
270+ this . datePicker ?. closedStream . subscribe ( ( ) => this . cleanup ( ) ) ;
271+ }
272+
273+ ngOnDestroy ( ) {
274+ this . cleanup ( ) ;
275+ }
276+
277+ private cleanup ( ) {
278+ this . removeClickListener ?.( ) ;
279+ this . removeClickListener = undefined ;
241280 }
242281
243282 ngOnChanges ( changes : any ) {
@@ -247,6 +286,9 @@ export class PlexDateTimeComponent implements AfterViewInit, OnChanges, ControlV
247286 }
248287 }
249288
289+ private removeClickListener ?: ( ) => void ;
290+
291+
250292 writeValue ( value : any ) {
251293 this . _value = value ? moment ( value ) . toDate ( ) : null ;
252294 this . timeString = this . _value ? moment ( this . _value ) . format ( 'HH:mm' ) : '' ;
@@ -318,12 +360,10 @@ export class PlexDateTimeComponent implements AfterViewInit, OnChanges, ControlV
318360 registerOnTouched ( fn : ( ) => void ) { this . onTouched = fn ; }
319361 setDisabledState ( isDisabled : boolean ) { this . disabled = isDisabled ; }
320362
363+
321364 // type === 'date'
322365 onDateChange ( ev : any ) {
323366 const input = ev . targetElement ?. value || ev . target ?. value ;
324- if ( ! input ) {
325- return ;
326- }
327367 const m = moment ( input , this . _format ) ;
328368 this . _value = m . isValid ( ) ? m . toDate ( ) : null ;
329369 this . emitChange ( true ) ;
0 commit comments