ngb-datepicker在角材料输入(matInput)中不起作用

时间:2019-06-12 12:05:30

标签: angular ngb-datepicker

我想在材料Input中使用ngb-datepicker。我成功地将datepicker应用于了mat输入。但存在月份和年份下拉菜单的问题。

我尝试了以下代码段:

<mat-form-field>
<input matInput placeholder="Select Valid Till" name="GodownValidTill" [(ngModel)]="GodownValidTill" ngbDatepicker #d2="ngbDatepicker" required readonly>
<mat-icon style="float:right;height:20px;width:20px;" (click)="d2.toggle()" svgIcon="calendar" title="Calendar"></mat-icon>
</mat-form-field>

有完美解决方案的任何解决方案吗?

3 个答案:

答案 0 :(得分:4)

我尝试重现此问题,发现默认情况下ngbDatePicker附加在它所附加的输入字段的正下方。当我们使用matInput时,实际的输入字段会被包裹在各种材料类中,这些材料类会导致日期选择器出现问题。

因此,我们可以做的是,可以使用ngbDatepickercontainer属性将日期选择器附加到正文中。容器属性当前仅支持“ body”作为值。

    <mat-form-field>
            <input matInput type="text" ngbDatepicker container="body" #d="ngbDatepicker" (click)="d.open()" placeholder="Date Picker with issue"/>
    </mat-form-field>

这里是stackblitz demo。我希望这会有所帮助。

答案 1 :(得分:2)

我不确定到底是什么问题,但是将两个库集成在一起没有问题。我使用的代码几乎和您完全一样。

<mat-form-field class="example-full-width">
  <input matInput placeholder="Favorite food"  name="GodownValidTill" [(ngModel)]="GodownValidTill" (ngModelChange)="onSelect($event)" ngbDatepicker #d="ngbDatepicker" required readonly>
  <mat-icon (click)="d.toggle()">calendar-today</mat-icon>
</mat-form-field>

从功能上讲,没有问题。但是,当然,您需要对CSS /样式进行自己的更改。我已通过here复制了一个演示。

为什么不同时使用这两个库,为什么不同时使用Angular Boostrap或Angular Material?这样,您无需管理不同的程序包。这两个库都有其自己的Datepicker组件(Material Datepicker / Ngbootstrap Datepicker)。

答案 2 :(得分:1)

另一个方法是格式化日期选择器。参见final result

第一步是创建自定义标题

<div class="mat-calendar-header">
  <div class="mat-calendar-controls">
    <button mat-icon-button type="button" class="mat-calendar-previous-button arrow"
            [disabled]="!previousEnabled()" (click)="customPrev()"
            [attr.aria-label]="prevButtonLabel">
    </button>
    <select [ngModel]="dateMonth" (ngModelChange)="dateMonth=$event;select()"class="custom-select">
    <option *ngFor="let month of months;let i=index" [value]="i">{{month}}</option>
    </select>
    <select [ngModel]="dateYear" (ngModelChange)="dateYear=+$event;select()" class="custom-select" style="width:70%" >
    <option *ngFor="let i of [-10,-9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8,9,10]" [value]="dateYear+i">{{dateYear+i}}</option>
    </select>
    <button mat-icon-button type="button" class="mat-calendar-next-button arrow"
            [disabled]="!nextEnabled()" (click)="customNext()"
            [attr.aria-label]="nextButtonLabel">
    </button>
  </div>
</div>

使用.css外观类似于ngb-datepicker

.custom-select {
    display: inline-block;
    width: 100%;
    height: calc(1.5em + .75rem + 2px);
    padding: .375rem 1.75rem .375rem .75rem;
    font-size: .8rem;
    font-weight: 200;
    line-height: 1.5;
    color: #495057;
    vertical-align: middle;
    background: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3e%3cpath fill='%23343a40' d='M2 0L0 2h4zm0 5L0 3h4z'/%3e%3c/svg%3e") right .75rem center/8px 10px no-repeat #fff;
    border: 1px solid #ced4da;
    border-radius: .25rem;
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
}
.arrow{
  margin-top: -.25rem;
}

如果标题扩展了MatCalendarHeader,则可以实现OnInit-将值放入Year和Month的组合框中,并添加ElementRef和Renderer2。我使用Renderer2添加/删除类removeRow

.removeRow tbody tr:first-child td{
  display:none
}

当月份的第一天的日期为Sundoay,Monday或Thrusday时,这使我们不显示第一行-在物料日期选择器中显示月份,但在组合中将其显示-框。

export class ExampleHeader extends MatCalendarHeader<any> implements OnInit {
  calendar:any
  months=[
    "January","February","March","April","May","June","July","August","September","October","November","December"]

  dateYear:any
  dateMonth:any

  constructor(_intl:MatDatepickerIntl,
      _calendar: MatCalendar<any>, _dateAdapter: DateAdapter<any>,
      @Inject(MAT_DATE_FORMATS) _dateFormats: MatDateFormats, cdr: ChangeDetectorRef,private el:ElementRef,private render:Renderer2){
    super(_intl,_calendar,_dateAdapter,_dateFormats,cdr)
        this.calendar=_calendar;
        this.dateYear=this.calendar.activeDate?this.calendar.activeDate.getFullYear():new Date().getFullYear()
        this.dateMonth=this.calendar.activeDate?this.calendar.activeDate.getMonth():new Date().getMonth()
  }
  select()
  {
    this.calendar.activeDate=new Date(this.dateYear,this.dateMonth)
    this.refreshCombo(this.dateMonth,this.dateYear)
  }
  ngOnInit()
  {
    this.refreshCombo(this.calendar.activeDate.getMonth(),this.calendar.activeDate.getFullYear())
  }
  refreshCombo(month,year)
  {
     this.dateMonth=month;
     this.dateYear=year;
     const element=this.el.nativeElement.parentElement
     if (new Date(year,month,1).getDay()<=2)
      this.render.addClass(element,'removeRow')
     else
      this.render.removeClass(element,'removeRow')
  }

  /** Handles user clicks on the previous button. */
  customPrev(): void {
    this.previousClicked()
    this.refreshCombo(this.calendar.activeDate.getMonth(),this.calendar.activeDate.getFullYear());
  }

  /** Handles user clicks on the next button. */
  customNext(): void {
    this.nextClicked()
     this.refreshCombo(this.calendar.activeDate.getMonth(),this.calendar.activeDate.getFullYear());
 }