将日期范围添加到 NgbInputDatepicker 输入字段

Add date range to NgbInputDatepicker input field

我正在使用 Angular 5.2 和 ngbootstrap 1.1。该库有几个不同的日期选择器选项,一个用作组件,另一个用作指令。

我正在使用指令。下面是一个 link 示例,说明如何使用模板设置 ngbootstrap 的指令。

directive example

选择两个日期时,popover在输入内添加了一个日期。

在我最初的方法中,我尝试设置

[(ngModel)]=model 

 this.model = `${this.fromDate} / ${this.toDate}`;

然而,我在设置模型后才意识到这一点。在 ngbootstrap 的日期选择器模块 .

提供的另一个组件中检查了日期
private _fromDateStruct(date: NgbDateStruct): NgbDate {
  const ngbDate = date ? new NgbDate(date.year, date.month, date.day) : null;
  return this._calendar.isValid(ngbDate) ? ngbDate : null;
}

link to component code

此外,上面的私有方法使得无法扩展 class 和覆盖检查

class DateInputDirective extends NgbInputDatepicker 

深挖了一点,希望能换个服务。 NgbDateAdapter 服务 returns 对象,如果不准确则为 null。我的字符串日期范围无法通过。

NgBootstrap API

fromModel(date: NgbDateStruct): NgbDateStruct {
  return (date && date.year && date.month && date.day) ? {year: date.year, month: date.month, day: date.day} : null;

}

另外,我利用了 angular 的 useClass 并插入了一个字符串条件。

{
    provide: NgbDateAdapter,
    useClass: NgbStringAdapter
},

但是,NgbDatePickerInput class 覆盖了此 class 完成之前的行为。

不确定我是否遗漏了一些非常简单的东西,或者是否是多使用几次 extends 或 useClass 的问题。但我肯定正在寻找对此的一些见解。 stackblitz link 不是我的实际代码,但它很好地代表了我的开始。如果有什么地方写不清楚,请随时与我们联系。谢谢!

使用 ElementRefViewChild 设置输入值即可。

我的意思是不将 ViewChild 与 Directive/Component( NgbInputDatepicker ) 一起使用,因为指令中元素的所有访问器都是私有的,我不知道如何更改输入除非在 _writeModelValue 方法中 (line 363) , writeValue 调用它,但它只更新一个日期。

所以步骤是:

  • 通过使用 ElementRefViewChild 来获得输入元素,
  • Renderer2 用于设置其值(就像指令一样)
  • 并使用 NgbDateParserFormatter 格式化模型日期
  • 你只需要在选择日期时这样做,所以在方法onDateSelection

这是主要代码,我会添加一些注释:

HTML:

<input
     #myRangeInput
    class="form-control" 
    placeholder="mm/dd/yyyy"
    name="dp" 
    [(ngModel)]="model" 
    ngbDatepicker 
    [dayTemplate]="t"
    [autoClose]="false"
    [displayMonths]="2"
    [maxDate]="maxDate"
    [minDate]="minDate"
>
    <ng-template #t let-date="date" let-focused="focused">
        <span class="custom-day"
            [class.range]="isFrom(date) || isTo(date) || isInside(date) || isHovered(date)"
            [class.faded]="isHovered(date) || isInside(date)"
            (click)="onDateSelection(date)"
            (mouseenter)="hoveredDate = date"
            (mouseleave)="hoveredDate = null"
            >
        {{ date.day }}
        </span>
    </ng-template>

打字稿:

import {Component, ViewChild, OnInit, ElementRef, Renderer2} from '@angular/core';
import {
    NgbDatepicker, 
    NgbInputDatepicker, 
    NgbDateStruct, 
    NgbCalendar, 
    NgbDateAdapter,
    NgbDateParserFormatter} from '@ng-bootstrap/ng-bootstrap';
...
export class NgbdDatepickerPopup implements OnInit{
  ...
 @ViewChild('myRangeInput') myRangeInput: ElementRef;
 constructor(element: ElementRef, private renderer: Renderer2, private _parserFormatter: NgbDateParserFormatter) { }
 onDateSelection(date: NgbDateStruct) {
        let parsed = ''; // initializing with empty string
        if (!this.fromDate && !this.toDate) {
            this.fromDate = date;
        } else if (this.fromDate && !this.toDate && after(date, this.fromDate)) {
            this.toDate = date;
            this.input.close();
        } else {
            this.toDate = null;
            this.fromDate = date;
        }
        if(this.fromDate) {
          // if fromDate is set: add the first date
          parsed += this._parserFormatter.format(this.fromDate);
        }
        if(this.toDate) {
          // if toDate is set: add the second date with separator
          parsed += ' - ' + this._parserFormatter.format(this.toDate);
        }
        // here we update the input value with the new parsed value
        this.renderer.setProperty(this.myRangeInput.nativeElement, 'value', parsed);
    }

这是工作演示:https://stackblitz.com/edit/angular-skbpc8-maun8a

以上答案是正确的,如果我有所需的声誉,我会发表评论,但由于我不能,这里是 css 的片段,您可以添加到 styles.css 以完成功能。

.ngb-dp-day.disabled[_ngcontent-c21], .ngb-dp-day.hidden[_ngcontent-c21] {
  cursor: default;
  color: #d0d0d0;
  pointer-events: none;
  -webkit-user-select: none; /* Chrome all / Safari all */
  -moz-user-select: none;   /* Firefox all */
  -ms-user-select: none;  /* IE 10+ */
   user-select: none;  /* Likely future */
}

这将使 min/maxDate 或 markDisabled 日期之前的禁用看起来褪色且无法选择。