我的datepicker中有required
属性。如果我触摸了日期选择器而我没有选择任何内容,那就无效了。这是一个公认的场景,我想要那样。
但是,如果我只选择一个日期并退出日期选择器,那也是有效的,但我希望它只有在日期是一个句点时才有效。
我的datepicker有很多代码。因此,创造Plunker更舒适。
我使用我的组件:
<div style="width: 200px;">
<mae-datepicker mode="period" [(ngModel)]="period" label="Period picker" required></mae-datepicker>
</div>
// tslint:disable:no-forward-ref
@Component({
selector: 'mae-datepicker',
templateUrl: './datepicker.html',
changeDetection: ChangeDetectionStrategy.OnPush,
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => DatepickerComponent),
multi: true
},
DatepickerService
],
host: {
class: 'datepicker input-form',
'[attr.tabindex]': 'getTabIndex()'
}
})
export class DatepickerComponent implements AfterViewInit, OnInit, OnChanges, OnDestroy, ControlValueAccessor {
@Input('required') isRequired: boolean = false
@Input() mode: string
@Input() availableDates: Date[]
@Input() availableDatesFn: (d: Date) => boolean
@Input() minDate: Date
@Input() maxDate: Date
@Output() onClose: EventEmitter<any> = new EventEmitter()
@ViewChild('datePickerPopup') datePickerPopup: DropdownDirective
selectionLabel: string
subscriptions: Subscription[] = []
private _model: Date | Date[]
private initialized: boolean = false
constructor(
private datepickerService: DatepickerService,
private cd: ChangeDetectorRef,
private ms: MomentService,
private _elementRef: ElementRef
) {
}
ngOnInit() {
if (!this.model) {
// init placeholder
this.model = null
}
if (!this.initialized) {
this.datepickerService.update(this.isRequired, this.availableDates, this.availableDatesFn, this.minDate, this.maxDate)
this.initialized = true
}
if (this.mode === 'period') {
this.datepickerService.updateSelectedPeriod(this.model ? this.model[0] : null, this.model ? this.model[1] : null)
} else {
this.datepickerService.updateSelectedDate(this.model)
}
ngOnChanges(): void {
this.isRequired = this.isRequired !== undefined && this.isRequired !== false
this.datepickerService.update(this.isRequired, this.availableDates, this.availableDatesFn, this.minDate, this.maxDate)
}
set model(val: Date | Date[]) {
if (val === this._model) {
return
}
this.updateModel(val)
this.onChange(val)
}
get model() {
return this._model
}
_updateDisplayedLabel(): void {
let val = this.model
if (this.mode === 'period') {
if (!Array.isArray(val) || val.length !== 2 || !val[0] || !val[1] ) {
this.selectionLabel = this.placeholder
} else {
this.selectionLabel = this.format(val[0]) + ' - ' + this.format(val[1])
}
}
}
updateModel(val: any) {
this._model = val
if (this.mode === 'period') {
//noinspection TypeScriptUnresolvedVariable
if (!Array.isArray(val) || val.length !== 2) {
val = [null, null]
}
this.datepickerService.updateSelectedPeriod(val[0], val[1])
} }
public selectDate = (date) => {
if (this.mode === 'period') {
const dates = this.model ? [this.model[0], this.model[1]] : [null, null]
if (!dates[0] || dates[1]) {
dates[0] = date
dates[1] = null
} else {
dates[1] = date
}
if (dates[0] && dates[1] && dates[0].getTime() > dates[1].getTime()) {
const d = dates[0]
dates[0] = dates[1]
dates[1] = d
}
this.model = dates
} else if (this.mode === 'multi') {
if (!this.model) {
this.model = [date]
} else {
const idx = (<Date[]> this.model).map(d => d.getTime()).indexOf(date.getTime())
const dates = [...(<Date[]> this.model)]
if (idx >= 0) {
dates.splice(idx, 1)
} else {
dates.push(date)
}
this.model = dates
}
} else {
this.model = date
this.closePopup()
}
}
}
&#13;
**#datepicker.service.ts#**
import { Injectable } from '@angular/core'
import { MomentService } from '../../../shared/services/moment.service'
export interface DatepickerDay {
currentMonth: boolean,
date: Date,
dateOfMonth: number,
disabled: boolean
inPeriod?: boolean,
selected?: boolean,
selectedPeriodStart: boolean,
selectedPeriodEnd: boolean,
today: boolean
}
@Injectable()
export class DatepickerService {
public currentYear
public currentMonth
public currentDay
public monthDays: DatepickerDay[] = []
// mode === period
private selectedPeriodStart
private selectedPeriodEnd
private notNull
constructor(
public update(required: boolean, availableDates: Date[], availableDatesFn: (d: Date) => boolean, minDate: Date, maxDate: Date) {
this.notNull = required
this.minAvailableDate = minDate ? this.ms.moment(minDate).startOf('day') : null
this.maxAvailableDate = maxDate ? this.ms.moment(maxDate).startOf('day') : null
this.updateMonthDays()
}
public updateSelectedPeriod = (selectedPeriodStart, selectedPeriodEnd) => {
if (selectedPeriodStart
&& this.isAvailable(selectedPeriodStart)) {
this.selectedPeriodStart = this.ms.moment(selectedPeriodStart).startOf('day')
} else {
this.selectedPeriodStart = selectedPeriodStart
}
if (selectedPeriodEnd
&& this.isAvailable(selectedPeriodEnd)) {
this.selectedPeriodEnd = this.ms.moment(selectedPeriodEnd).startOf('day')
this.currentYear = this.selectedPeriodEnd.year()
this.currentMonth = this.selectedPeriodEnd.month()
} else {
this.selectedPeriodEnd = null
}
this.updateMonthDays()
}
}
&#13;
谢谢!