ngx-bootstrap datepicker选项仅选择月份和年份

时间:2018-07-05 21:24:34

标签: angular ngx-bootstrap

我正在使用ngx-botstrap BsDatepickerModule作为我的申请表,我只需要选择一个月。有谁知道我在哪里可以找到解决方案? issue大约一年前就提出来了,看起来要求很高,所以我希望得到答案。 单击日期选择器按钮后,我希望看到的是: enter image description here

6 个答案:

答案 0 :(得分:3)

我设法使用相同的bsDatepicker来解决此问题,并且花费了最小的努力

组件模板:

<form class="container">
<input [(ngModel)]="modelDate" autocomplete="off" class="form-control" name="date" bsDatepicker [bsConfig]="{dateInputFormat: 'MM/YYYY'}" (onShown)="onOpenCalendar($event)">
Result: <p>{{modelDate}}</p>
</form>

组件代码示例:

onOpenCalendar(container) {
 container.monthSelectHandler = (event: any): void => {
   container._store.dispatch(container._actions.select(event.date));
 };     
 container.setViewMode('month');
}

在此处https://stackblitz.com/edit/ngx-datepicker-month-picker-poc

检查工作示例

答案 1 :(得分:1)

有时候,我是基于ng-bootstrap ngbDropdownToggle(不是ngx-bootstrap,但基于ngx-bootstrap的代码必须类似)制作一个月月日期选择器

代码在https://stackblitz.com/edit/angular-zs1rxp

基本是使用显示月份或年份的DropDownToggle

<div class="btn-group" ngbDropdown #calendarPanel="ngbDropdown">
  <input type="text" class="form-control" id="data" name="data" [(ngModel)]="dataTxt" [placeholder]="mask" #item (input)="change(item.value)">
  <button class="btn btn-outline-primary dropdown-toggle-split" ngbDropdownToggle>
    <i class="fa fa-calendar" aria-hidden="true"></i>
  </button>
  <div ngbDropdownMenu class="dropdown-menu">
    <div class="row">
      <button class="btn btn-link col-4" (click)="addYear($event,-1)">
        <span class="fa fa-chevron-left"></span>
      </button>
      <button *ngIf="!isyear" class="btn btn-link col-4" (click)="showYear($event,true)">{{data.year}}</button>
      <button *ngIf="isyear" class="btn btn-link col-4" (click)="showYear($event,false)">{{incr+1}}-{{incr+10}}</button>
      <button class="btn btn-link col-4" (click)="addYear($event,+1)">
        <span class="fa fa-chevron-right"></span>
      </button>
      <div *ngFor="let month of months; let i = index; let first = first; let last = last" class="col-4" (click)="selectYearMonth($event,i)">
        <div [ngClass]="{'select': !isyear?(i+1)==data.month:(i+incr)==data.year,'outrange':isyear && (first || last)}" class="card-body">
          <span *ngIf="!isyear">{{month}}</span>
          <span *ngIf="isyear">{{i+incr}}</span>
        </div>
      </div>
    </div>
  </div>
</div>

“键”是显示月份(带有月份名称的数组)或i + incr,其中incr是(year-year%10)-1

.ts很复杂,因为我们制作了一个自定义表单组件

interface Idata {
  month: number;
  year: number;
}
@Component({
  selector: 'month-date-picker',
  templateUrl: './month-date-picker.component.html',
  styleUrls: ['./month-date-picker.component.css'],
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => MonthDatePickerComponent),
      multi: true
    }
  ]
})
export class MonthDatePickerComponent implements ControlValueAccessor {

  data: Idata;
  dataTxt: string;
  separator: string;
  monthFirst: boolean;
  place: number;

  isyear:boolean=false;
  incr:number=0;


  months: string[] = ["ene", "feb", "mar", "abr", "may", "jun", "jul", "ago", "sep", "oct", "nov", "dic"];
  // Allow the input to be disabled, and when it is make it somewhat transparent.
  @Input() disabled = false;
  @Input() mask = "mm-yyyy";

  @ViewChild('calendarPanel') calendar: NgbDropdown; 

  constructor() {
    this.separator = this.mask.replace(/m|y|M/gi, "");
    this.monthFirst = this.mask.indexOf('y') > 0;
    this.place = this.mask.indexOf(this.separator);
  }

  change(value: string) {
    value=this.separator==" "?value.replace(/\.|-|\//," "):
          this.separator=="/"?value.replace(/\.|-| /,"/"):
          this.separator=="-"?value.replace(/\.| |\/ /,"-"):
          value.replace(/.| |\/ /,"-");

    let lastchar = value.substr(value.length - 1);
    if (lastchar == this.separator && value.length <= this.place) {
      if (this.monthFirst) {
        value = "0" + value;
      }
    }
    if (value.length > this.place && value.indexOf(this.separator) < 0) {
      value = value.substr(0, value.length - 1) + this.separator + lastchar;
    }
    this.dataTxt = value;
    let items = value.split(this.separator);
    if (items.length == 2) {
      let year = this.monthFirst ? items[1] : items[0];
      let month = this.monthFirst ? items[0] : items[1];
      let imonth = this.months.indexOf(month);
      if ((imonth) < 0)
        imonth = parseInt(month);
      else
        imonth = imonth + 1;

      let iyear = parseInt(year);
      if (iyear < 100)
        iyear = iyear + 2000;
      this.data = {
        year: iyear,
        month: imonth
      }
      this.incr=this.getIncr(this.data.year);
    }
    this.writeValue(this.data);

  }
  selectYearMonth($event,index:number)
  {
    if (this.isyear)
    {
      $event.stopPropagation();
      this.data.year=index+this.incr;
      this.dataTxt=this.formatData(this.data);
      this.isyear=false;
      this.incr=this.getIncr(this.data.year);
    }
    else{
    this.data.month=index+1;
    this.dataTxt=this.formatData(this.data);
    }
  }
  showYear($event:any,show:boolean)
  {
    $event.stopPropagation();
    this.isyear=!this.isyear;
  }
  addYear($event:any,incr:number)
  {
    $event.stopPropagation(); 
    let year=this.isyear?this.data.year+10*incr:this.data.year+incr;
    console.log(year);
    this.data.year=year;
    this.incr=this.getIncr(year);
    this.dataTxt=this.formatData(this.data);
  }
  onChange = (data: Idata) => {
    this.data = data;
    this.dataTxt = this.monthFirst ? "" + data.month + this.separator + data.year :
      "" + data.year + this.separator + data.month;
      this.incr=this.getIncr(this.data.year);
  };

  getIncr(year:number):number
  {
    return (year-year%10)-1;
  }
  formatData(data:Idata):string
  {
    let monthTxt=data.month<10? "0"+data.month:"" + data.month;
    return  this.monthFirst ?  monthTxt+ this.separator + data.year :
    "" + data.year + this.separator + monthTxt

  }
  // Function to call when the input is touched (when a star is clicked).
  onTouched = () => { };

  writeValue(data: Idata): void {
    this.data = data;
    this.onChange(this.data)
  }

  // Allows Angular to register a function to call when the model (rating) changes.
  // Save the function as a property to call later here.
  registerOnChange(fn: (data: Idata) => void): void {
    this.onChange = fn;
  }

  // Allows Angular to register a function to call when the input has been touched.
  // Save the function as a property to call later here.
  registerOnTouched(fn: () => void): void {
    this.onTouched = fn;
  }

  // Allows Angular to disable the input.
  setDisabledState(isDisabled: boolean): void {
    this.disabled = isDisabled;
  }
}

注意:很抱歉,我的代码取决于字体,而且在堆栈bliz中看不到

答案 2 :(得分:1)

查看有关使用可能的选项#2627

的问题

答案 3 :(得分:1)

此请求已应用并实现,在3.1.3 ngx-bootstrap版本中可用 这是DEMO

这是一个CHANGELOG

答案 4 :(得分:1)

以下是想通过bsDatepicker仅实现选择器的解决方案:

仅用于月份选择器:

onOpenCalendarMonth(container) {

     container.setViewMode('month');

     container.monthSelectHandler = (event: CalendarCellViewModel): void => {

     container.value =  event.date;

     return;
 };    
}

仅用于年份选择器:

onOpenCalendarYear(container) {

     container.setViewMode('year');

     container.yearSelectHandler = (event: CalendarCellViewModel): void => {

     container.value =  event.date;

     return;
 };    
}

希望这对某人有帮助,谢谢!

答案 5 :(得分:0)

只需将minMode:'month'放在bsConfig中,对我来说就很好了。

[bsConfig] =“ {minMode:'month',AdaptativePosition:true,dateInputFormat:'MMMM YYYY'}”