ng2-ui / datetime-picker

Angular2 DateTime Picker
https://ng2-ui.github.io/#/datetime-picker
MIT License
121 stars 62 forks source link

datetime-picker close issue #161

Closed JayaniSumudini closed 7 years ago

JayaniSumudini commented 7 years ago

datetime picker has a issue in close date picker ,when clicking the input box, without selecting date.

allenhwkim commented 7 years ago

Please be more specific by following issue template.

negberts commented 7 years ago

Can you at least make closeOnSelect a boolean input instead of string? It probably has something to do with that.

negberts commented 7 years ago

And is it really necessary to check for the hideDatetimePicker method? I guess in different browsers mouse events get handled differently. We have to click somewhere far from the overlay to get the picker to close.

allenhwkim commented 7 years ago

@negberts Please be more specific. We also have x button to close.

negberts commented 7 years ago

You only have the X button when close-on-select = false. When true you don't have it.

I think you should update the method hideDatetimePicker to return true at some point. It only returns false now:

hideDatetimePicker = (event?): any => {

    if (this.clickedDatetimePicker) {

      return false;

    } else {  /* invoked by function call */

      this.componentRef.destroy();

      this.componentRef = undefined;

      this.popupClosed$.emit(true);

    }

    event && event.stopPropagation();

  };

so this.closeOnSelect !== "false" && this.hideDatetimePicker(); will probably never be true.

negberts commented 7 years ago

I would probably do something like

dateSelected = (date) => {

    this.el.tagName === 'INPUT' && this.inputElValueChanged(date);

    this.valueChanged$.emit(date);

    if(this.closeOnSelect && !this.clickedDatetimePicker)
     this.hideDatetimePicker();

  };

hideDatetimePicker = (event?): any => {

    this.componentRef.destroy();

      this.componentRef = undefined;

      this.popupClosed$.emit(true);

   if(event) event.stopPropagation();

  };
negberts commented 7 years ago

See the recording for another issue. Overlay doesn't close while clicking at several other places of the application

Recording #1.zip

allenhwkim commented 7 years ago

@negberts hmm. that did not happened to me. Can you make plunker example to replicate that issue?

allenhwkim commented 7 years ago

@negberts The problem that I see from your screencast is that input field does not lose focus. The overlay become hidden only when the input loses focus at the moment.

allenhwkim commented 7 years ago

I see

if you clicked on datetime picker, then click on document, it does not close

if you do NOT click on datetime picker and click on document, it does close.

I will see what I can do.

negberts commented 7 years ago

We are getting there...

I now get an error of 'Cannot read property 'type' of undefined at ViewContainer.detachView' the first time I select a date. (with close-on-select=true)

negberts commented 7 years ago

Update: no error when we click outside the datepicker, the datepicker is then closed without error. When we click the X we get the same error too.

negberts commented 7 years ago

It probably has something to do with the timing of clicking on the component and destroying the component while it is still visible. Maybe start with setting display:none to the div with class "ng2-datetime-picker" and destroy the component in the ngDestroy hook?

negberts commented 7 years ago

I have a branch/PR available if you give me access :)

negberts commented 7 years ago

In the component:

<div class="closing-layer" (click)="close()" *ngIf="showCloseLayer && visible" ></div>
<div class="ng2-datetime-picker" *ngIf="visible">

@Input('visible') visible: boolean = false;

In the directive:

import { ComponentFactoryResolver, ComponentRef, Directive, EventEmitter, Host, Input, OnChanges, OnInit, Optional, Output, SimpleChanges, SkipSelf, ViewContainerRef, OnDestroy } from '@angular/core';

export class Ng2DatetimePickerDirective implements OnInit, OnChanges, OnDestroy

private componentVisible: boolean = false;

ngOnDestroy() {
     if(this.sub) {
      this.sub.unsubscribe();
    }

     if(this.componentRef) {
       this.componentRef.destroy();
       this.componentRef = undefined;
     }
 }
//show datetimePicker element below the current element
  showDatetimePicker = (event?): void =>  {
    this.componentVisible = true;
    if (this.componentRef) { /* if already shown, do nothing */
      return;
    }

    let factory = this.resolver.resolveComponentFactory(Ng2DatetimePickerComponent);

    this.componentRef   = this.viewContainerRef.createComponent(factory);
    this.ng2DatetimePickerEl = this.componentRef.location.nativeElement;
    this.ng2DatetimePickerEl.setAttribute('tabindex', '32767');
    this.ng2DatetimePickerEl.addEventListener('mousedown', (event) => {
      this.clickedDatetimePicker = true
    });
    this.ng2DatetimePickerEl.addEventListener('mouseup', (event) => {
      this.clickedDatetimePicker = false
    });
    this.ng2DatetimePickerEl.addEventListener('blur', (event) => {
      this.hideDatetimePicker();
    });

    let component = this.componentRef.instance;
    component.defaultValue   = <Date>this.defaultValue || <Date>this.el['dateValue'];
    component.dateFormat     = this.dateFormat;
    component.dateOnly       = this.dateOnly;
    component.timeOnly       = this.timeOnly;
    component.minuteStep     = this.minuteStep;
    component.minDate        = <Date>this.minDate;
    component.maxDate        = <Date>this.maxDate;
    component.minHour        = <number>this.minHour;
    component.maxHour        = <number>this.maxHour;
    component.disabledDates  = this.disabledDates;
    component.showCloseButton = this.closeOnSelect === false;
    component.showCloseLayer = this.showCloseLayer;
    component.visible        = this.componentVisible;

    this.styleDatetimePicker();

    component.selected$.subscribe(this.dateSelected);
    component.closing$.subscribe(() => {
      this.hideDatetimePicker();
    });

    //Hack not to fire tab keyup event
    // this.justShown = true;
    // setTimeout(() => this.justShown = false, 100);
  };
hideDatetimePicker = (event?): any => {
    if (this.clickedDatetimePicker) {
      return false;
    } else {  /* invoked by function call */
      this.componentVisible = false;
      this.popupClosed$.emit(true);
    }
    event && event.stopPropagation();
  };
allenhwkim commented 7 years ago

This has been fixed with the recent version, right?

allenhwkim commented 7 years ago

closing this. please re-open if problem continues