Опция ngx-bootstrap datepicker для выбора только месяца и года

Я использую ngx-botstrap для моей заявки и у меня есть требование выбрать только месяц. Кто-нибудь знает, где я могу найти решение? Эта проблема была поднята почти год назад и выглядит очень серьезной. — спросил я, поэтому таю надежду получить ответ. Вот что я хотел бы видеть после нажатия кнопки выбора даты: введите здесь описание изображения


person dim0_0n    schedule 05.07.2018    source источник


Ответы (6)


Мне удалось решить это с помощью того же 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

person dahool    schedule 12.11.2018
comment
интересно, что даже несмотря на то, что мой ответ - единственный, который действительно решает проблему без написания совершенно нового компонента, некоторые провалы # & не голосуют за него. - person dahool; 13.11.2018
comment
При выборе даты рождения гораздо удобнее начать с года, затем автоматически измениться на месяц, а затем на день. Я добился этого, вдохновленный этим примером. Простое изменение вида в обработчике выбора сделало свое дело. Спасибо :-) - person Jette; 09.03.2019
comment
Как сделать будущие месяцы отключенными? Пробовал использовать maxDate, но это не работает. Он отключен, но пользователи все еще могут его выбрать. - person Object Manipulator; 17.09.2019

Просто поместите minMode:'month' в bsConfig, у меня это отлично сработало.

[bsConfig]="{ minMode:'month', adaptivePosition: true, dateInputFormat: 'MMMM YYYY' }"
person Kamran Sohail    schedule 03.12.2020
comment
Это должен быть принятый ответ, поскольку он встроен в библиотеку. - person jpf; 30.12.2020
comment
minMode был представлен как часть bsconfig. это решение синхронизировано с последней библиотекой. Я проверил это. - person Devesh G; 05.05.2021

Вот решения, которые хотели реализовать только средство выбора месяца или года с помощью 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;
 };    
}
person Nimesh khatri    schedule 19.05.2020

Некоторое время назад я сделал средство выбора даты месяца и года на основе 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 — (год-год%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;
  }
}

ПРИМЕЧАНИЕ. Извините, мой код зависит от потрясающего шрифта и не отображается в стеке.

person Eliseo    schedule 05.07.2018

См. проблему для возможной опции #2627

person Andrey Hideki Nakano    schedule 17.07.2018

Этот запрос применен и реализован, он доступен в версии 3.1.3 ngx-bootstrap. Это ДЕМО

А это CHANGELOG

person LudmilaN    schedule 10.12.2018