1

我已经实现的场景ion-datetime要求可以禁用某些日期。封锁日期。这在一般应用程序中相当普遍,例如Airbnb

据我所知,Ionic 附带的ion-datetime模块不支持禁用日期,而且我找不到支持日期和时间选择的外部库,该库可以实现到 Ionic 和工作的现代迭代中。

有没有人以优雅的方式解决了这个问题,或者有任何解决方案使 [Ionic] 原生日期选择器从选择轮禁用某些选择器选择天?

4

1 回答 1

0

最后我不得不调整自己的解决方案,没有任何线索。我想我会分享这个,以防其他人面临类似的情况(直到 Ionic 不可避免地在其核心中添加一些东西)。

这些说明假设您已经有设置阻止日期的解决方案,我建议使用ion2-calendar(及其多选模式)

因此,在您的 HTML 中,您将拥有如下内容:

<ion-datetime
    #orderDatePicker
    (click)="setUpListeners()"
    (ionChange)="setSelectedDateTime( orderDatePicker.value )"
    displayFormat="DD MMM YYYY HH:mm"
    max="2021"
    minuteValues="0,15,30,45"
    [min]="todaysDate"
    placeholder="SELECT"></ion-datetime>

TS 中的一些必需导入(下划线):

import * as _ from 'underscore/underscore';

在您的 TS 文件中,您必须在构造函数上方添加默认变量才能普遍使用:

@ViewChild('orderDatePicker', {read: ElementRef}) public orderDatePicker: ElementRef;
dayChangeObserver: any = null;
monthChangeObserver: any = null;
current_month_blockout_dates: any = null;

您需要一种方法来过滤到选定月份的阻止日期。

checkMonth( monthNumber: number ) {
    let dates = this.product.blockout_dates;
    if(dates) {
      let current_dates = dates.filter(dateObj => dateObj.months == monthNumber);
      return current_dates;
    }
    return [];
}

然后你会注意到我在 ion-datetime 的点击事件上设置了一个方法,所以它会设置一些侦听器,确切地说是突变观察器。

我已经注释了代码来解释它,但基本上滚动器使用样式来上下变换他们的 X 轴,所以突变观察者观察这些事件以了解何时进行更改 - 因为本机可用的 ionChange 事件仅在选择时触发过程。

结果显示或隐藏完成按钮。我正在使用 jQuery 使 javascript 选择更快一些(至少对我而言)。我还使用下划线实用工具带对突变观察者进行去抖动,否则它们在滚动时会触发太多次。

setUpListeners() {
    const self = this;
    if(!this.monthChangeObserver && this.current_month_blockout_dates.length > 0) {
      setTimeout(() => {
        const day_scroller    = $('.picker-col:nth-of-type(1) .picker-opt-selected');
        const month_scroller  = $('.picker-col:nth-of-type(2) .picker-opt-selected');

        // Whenever a month is scrolled
        this.monthChangeObserver = new MutationObserver(_.debounce(function() {
          let monthNumeric = (1+Number($('.picker-col:nth-of-type(2) .picker-opt-selected').attr('opt-index')));

          // Retrieve the blocked dates for the selected month
          this.current_month_blockout_dates = self.checkMonth(monthNumeric); // uses 'self' to step outside of mutation scope
          let bdates = this.current_month_blockout_dates;

          // Enable all days for the current month
          $(`.picker-col:nth-of-type(1) button.disabled`).removeClass('disabled');

          // Create an array of the blocked days
          let bdays = [];
          if(bdates.length > 0){
            bdates.reduce(function(previousVal, currentVal) { bdays.push(currentVal.date); }, 0);
          }

          // Cycle through that array and disable those day dates (visually)
          if(bdays.length > 0){
            bdays.reduce(function(prv, cur) {
              $(`.picker-col:nth-of-type(1) .picker-opt[opt-index=${cur}]`).addClass('disabled');
            }, 0);
          }

          // Disable or enable the "Done" button depending on whether or not the selected day is 'disabled' (after month is scrolled)
          if($(`.picker-col:nth-of-type(1) button.picker-opt-selected`).hasClass('disabled')) {
            $('.picker-toolbar-button:not(.picker-toolbar-cancel)').hide();
          } else {
            $('.picker-toolbar-button:not(.picker-toolbar-cancel)').show();
          }
        }, 100));

        // Whenever a day is scrolled
        this.dayChangeObserver = new MutationObserver(_.debounce(function() {
          let selected_day = $('.picker-col:nth-of-type(1) .picker-opt-selected');
          let dayNumeric = (1+Number(selected_day.attr('opt-index')));

          // Disable or enable the "Done" button depending on whether or not the selected day is 'disabled'
          if(selected_day.hasClass('disabled')) {
            $('.picker-toolbar-button:not(.picker-toolbar-cancel)').hide();
          } else {
            $('.picker-toolbar-button:not(.picker-toolbar-cancel)').show();
          }
        }, 100));

        this.dayChangeObserver.observe(day_scroller[0], { attributes : true, attributeFilter : ['style'], childList: false, characterData:false , subtree:false });
        this.monthChangeObserver.observe(month_scroller[0], { attributes : true, attributeFilter : ['style'], childList: false, characterData:false , subtree:false });
      }, 100); // Slight delay to allow the DOM to render
    }
  }

最后只需将 CSS 添加到 global.scss 文件中:

ion-picker-column {
    .picker-opts {
        .picker-opt {
            &.disabled {
                opacity: 0.25;
                text-decoration: line-through !important;
            }
        }
    }
}

划掉日期(日期)并隐藏完成按钮

于 2020-04-08T09:36:08.090 回答