ngx-bootstrap datepicker option to pick only month and a year

自古美人都是妖i 提交于 2019-12-25 00:28:06

问题


I'm using ngx-botstrap BsDatepickerModule for my application form and I have a requirement to pick only a month. Does anyone know where I can find a solution? This issue has been raised almost a year ago and looks like it is highly demanded, so I conceal a hope to get an answer. This is what I would like to see after clicking a date selector button:


回答1:


I managed to solve this using the same bsDatepicker, with minimal effort

Component template:

<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>

Component code sample:

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

Check working sample here https://stackblitz.com/edit/ngx-datepicker-month-picker-poc




回答2:


Sometime ago I make a month-year date picker based in ng-bootstrap ngbDropdownToggle (not in ngx-bootstrap, but I supouse the code must be similar in ngx-bootstrap

The code is in https://stackblitz.com/edit/angular-zs1rxp

The basic is using a DropDownToggle that show months or years

<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>

the "key" is show months (an array with the name of months) or i+incr, where incr is (year-year%10)-1

The .ts is complex because we make a custom form component

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;
  }
}

NOTE:Sorry, My code depending font-awesome and son't see in the stackbliz




回答3:


See the issue for featuring possible option #2627




回答4:


This request applied and implemented, it available in 3.1.3 ngx-bootstrap version This is a DEMO

And this is a CHANGELOG



来源:https://stackoverflow.com/questions/51200121/ngx-bootstrap-datepicker-option-to-pick-only-month-and-a-year

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!