@progress/kendo-angular-scheduler
Version:
Kendo UI Scheduler Angular - Outlook or Google-style angular scheduler calendar. Full-featured and customizable embedded scheduling from the creator developers trust for professional UI components.
472 lines (459 loc) • 22.2 kB
JavaScript
/**-----------------------------------------------------------------------------------------
* Copyright © 2025 Progress Software Corporation. All rights reserved.
* Licensed under commercial license. See LICENSE.md in the project root for more information
*-------------------------------------------------------------------------------------------*/
import { Component, ViewChildren, QueryList, Input } from '@angular/core';
import { RecurrenceService } from './recurrence.service';
import { isPresent } from '../../common/util';
import { dayRule, weekdayRule, weekendRule } from './recurrence.service';
import { RepeatOnRadioButtonDirective } from './repeat-on-radio-button.directive';
import { LocalizationService } from '@progress/kendo-angular-l10n';
import { NumericTextBoxComponent, NumericTextBoxCustomMessagesComponent } from '@progress/kendo-angular-inputs';
import { DropDownListComponent } from '@progress/kendo-angular-dropdowns';
import { NgIf } from '@angular/common';
import { LabelComponent, LabelDirective } from '@progress/kendo-angular-label';
import * as i0 from "@angular/core";
import * as i1 from "./recurrence.service";
import * as i2 from "@progress/kendo-angular-l10n";
/**
* @hidden
*/
export class RecurrenceMonthlyYearlyEditorComponent {
recurrence;
localization;
set userNumericOptions(options) {
this.numericOptions = { ...this.numericOptions, ...options };
}
repeatOnRadioButtons;
extendedWeekDays;
offsetPositions;
months;
currentMonthDay;
currentMonthMonthDay;
currentMonthWeekDay;
currentOffset;
currentWeekDay;
uniqueId;
numericOptions = {
min: 1,
max: 31,
format: '#',
autoCorrect: true,
step: 1,
spinners: true
};
subs;
constructor(recurrence, localization) {
this.recurrence = recurrence;
this.localization = localization;
this.uniqueId = this.recurrence.getUniqueId();
this.setInitialValues();
this.subscribeEventHandlers();
}
setInitialValues() {
this.extendedWeekDays = this.recurrence.extendedWeekDays;
this.offsetPositions = this.recurrence.offsetPositions;
this.currentOffset = this.defaultOffset;
this.currentWeekDay = this.defaultWeekDay;
if (this.currentFreq === 'yearly') {
this.months = this.recurrence.months;
this.currentMonthMonthDay = this.currentMonthWeekDay = this.recurrence.rrule.byMonth[0];
}
}
subscribeEventHandlers() {
this.subs = this.recurrence.repeatOnRuleChange.subscribe(this.onRepeatOnRuleChange.bind(this));
this.subs.add(this.recurrence.frequencyChange.subscribe(this.onFrequencyChange.bind(this)));
}
onRepeatOnRuleChange(newRepeatOnRule) {
if (newRepeatOnRule === 'monthday') {
this.recurrence.rrule.byMonthDay = [this.monthDay];
if (this.currentFreq === 'yearly') {
this.recurrence.rrule.byMonth = [this.currentMonthMonthDay];
}
}
else if (newRepeatOnRule === 'weekday') {
if (typeof this.weekDay === 'string') {
/* day, weekday or weekend */
this.recurrence.rrule.bySetPosition = [this.offset];
this.recurrence.rrule.byWeekDay = this.weekDayRuleFromString(this.weekDay);
}
else {
/* specific weekday */
this.recurrence.rrule.byWeekDay = [{
day: this.weekDay,
offset: this.offset
}];
}
if (this.currentFreq === 'yearly') {
this.recurrence.rrule.byMonth = [this.currentMonthWeekDay];
}
}
}
onFrequencyChange() {
this.setInitialValues();
}
ngOnDestroy() {
if (this.subs) {
this.subs.unsubscribe();
}
}
get monthDay() {
const rrule = this.recurrence.rrule;
if (isPresent(rrule.byMonthDay) && rrule.byMonthDay.length > 0) {
return rrule.byMonthDay[0];
}
else if (isPresent(this.currentMonthDay)) {
return this.currentMonthDay;
}
else {
return this.recurrence.start.getDate();
}
}
get weekDay() {
const rrule = this.recurrence.rrule;
if (isPresent(rrule.byWeekDay)) {
const weekDaysCount = rrule.byWeekDay.length;
switch (weekDaysCount) {
case 7:
return 'day';
case 5:
return 'weekday';
case 2:
return 'weekend';
case 1:
return rrule.byWeekDay[0].day;
default:
break;
}
}
else if (isPresent(this.currentWeekDay)) {
return this.currentWeekDay;
}
return this.defaultWeekDay;
}
get offset() {
const rrule = this.recurrence.rrule;
if (isPresent(rrule.byWeekDay)) {
const weekDaysCount = rrule.byWeekDay.length;
switch (weekDaysCount) {
case 7:
case 5:
case 2:
return rrule.bySetPosition[0];
case 1:
return rrule.byWeekDay[0].offset;
default:
break;
}
}
else if (isPresent(this.currentOffset)) {
return this.currentOffset;
}
return this.defaultOffset;
}
onMonthChange(month, repeatOnRule) {
if (repeatOnRule === 'monthday') {
this.currentMonthMonthDay = month;
}
else {
this.currentMonthWeekDay = month;
}
this.recurrence.setMonths([month]);
}
onMonthDayChange(monthDay) {
this.currentMonthDay = monthDay;
this.recurrence.monthDays = [monthDay];
}
onOffsetPositionChange(offset) {
const rrule = this.recurrence.rrule;
if (isPresent(rrule.byWeekDay)) {
const weekDaysCount = rrule.byWeekDay.length;
switch (weekDaysCount) {
case 7:
case 5:
case 2:
this.recurrence.positions = [offset];
break;
case 1:
rrule.byWeekDay[0].offset = offset;
this.recurrence.onChange();
break;
default:
break;
}
}
this.currentOffset = offset;
}
onWeekDayChange(weekDay) {
let weekDays;
if (typeof weekDay === 'string') {
/* day, weekday or weekend */
weekDays = this.weekDayRuleFromString(weekDay);
this.recurrence.positions = [this.offset];
}
else {
/* specific weekday */
this.recurrence.rrule.bySetPosition = null;
this.recurrence.rrule.byWeekDay = null;
weekDays = [{
day: weekDay,
offset: this.offset
}];
}
this.currentWeekDay = weekDay;
this.recurrence.setWeekDays(weekDays);
}
isDisabled(repeatOn) {
return this.recurrence.repeatOnRule !== repeatOn;
}
get currentFreq() {
return this.recurrence.frequency;
}
get defaultOffset() {
return 1;
}
get defaultWeekDay() {
return this.recurrence.start.getDay();
}
weekDayRuleFromString(weekDay) {
switch (weekDay) {
case 'day':
return dayRule;
case 'weekday':
return weekdayRule;
case 'weekend':
return weekendRule;
default:
break;
}
return null;
}
textForRepeatOn() {
const freq = this.currentFreq;
switch (freq) {
case 'monthly':
return this.textFor('monthlyRepeatOn');
case 'yearly':
return this.textFor('yearlyRepeatOn');
default:
break;
}
}
textFor(key) {
return this.localization.get(key);
}
onRepeatOnLabelClick() {
const selected = this.repeatOnRadioButtons.toArray().find(r => r.elem.checked);
if (selected) {
selected.elem.focus();
}
}
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RecurrenceMonthlyYearlyEditorComponent, deps: [{ token: i1.RecurrenceService }, { token: i2.LocalizationService }], target: i0.ɵɵFactoryTarget.Component });
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: RecurrenceMonthlyYearlyEditorComponent, isStandalone: true, selector: "kendo-recurrence-monthly-yearly-editor", inputs: { userNumericOptions: "userNumericOptions" }, viewQueries: [{ propertyName: "repeatOnRadioButtons", predicate: RepeatOnRadioButtonDirective, descendants: true }], ngImport: i0, template: `
<div class='k-form-field'>
<kendo-label
[text]="textForRepeatOn()"
labelCssClass="k-form-label"
(click)="onRepeatOnLabelClick()"
></kendo-label>
<div class="k-form-field-wrap">
<ul class='k-radio-list'>
<li class='k-radio-list-item'>
<span class="k-radio-wrap">
<input kendoRecurrenceRepeatOnRadioButton='monthday-{{uniqueId}}' />
</span>
<label [labelClass]="false" class='k-radio-label' for='k-repeaton-monthday-{{uniqueId}}'>
<ng-template [ngIf]="currentFreq === 'monthly'">
{{ textFor('monthlyDay') }}
</ng-template>
</label>
<ng-template [ngIf]="currentFreq === 'yearly'">
<kendo-dropdownlist
[data]='months'
textField='text'
valueField='value'
[value]='currentMonthMonthDay'
[valuePrimitive]='true'
(valueChange)="onMonthChange($event, 'monthday')"
[disabled]="isDisabled('monthday')"
[style.width.px]="170"
[style.margin]="'0 .4ex 0 1ex'">
</kendo-dropdownlist>
</ng-template>
<kendo-numerictextbox
class="k-recur-monthday"
[min]="numericOptions.min"
[max]="numericOptions.max"
[decimals]="0"
[format]="numericOptions.format"
[autoCorrect]="numericOptions.autoCorrect"
[readonly]="numericOptions.readonly"
[selectOnFocus]="numericOptions.selectOnFocus"
[spinners]="numericOptions.spinners"
[step]="numericOptions.step"
[title]="numericOptions.title"
[value]='monthDay'
(valueChange)='onMonthDayChange($event)'
[disabled]="isDisabled('monthday')"
>
<kendo-numerictextbox-messages
[increment]="textFor('numericIncrement')"
[decrement]="textFor('numericDecrement')"
>
</kendo-numerictextbox-messages>
</kendo-numerictextbox>
</li>
<li class='k-radio-list-item'>
<span class="k-radio-wrap">
<input kendoRecurrenceRepeatOnRadioButton='weekday-{{uniqueId}}' />
</span>
<label [labelClass]="false" class='k-radio-label' for='k-repeaton-weekday-{{uniqueId}}'></label>
<kendo-dropdownlist
[data]='offsetPositions'
textField='text'
valueField='value'
[value]='offset'
[valuePrimitive]='true'
(valueChange)='onOffsetPositionChange($event)'
[disabled]="isDisabled('weekday')"
[style.margin]="'0 .4ex 0 1ex'">
</kendo-dropdownlist>
<kendo-dropdownlist
[data]="extendedWeekDays"
textField='text'
valueField='value'
[value]='weekDay'
[valuePrimitive]='true'
(valueChange)='onWeekDayChange($event)'
[disabled]="isDisabled('weekday')"
[style.margin]="'0 .4ex 0 1ex'">
</kendo-dropdownlist>
<ng-template [ngIf]="currentFreq === 'yearly'">
<span>{{ textFor('yearlyOf') }}</span>
<kendo-dropdownlist
[data]='months'
textField='text'
valueField='value'
[value]='currentMonthWeekDay'
[valuePrimitive]='true'
(valueChange)="onMonthChange($event, 'weekday')"
[disabled]="isDisabled('weekday')"
[style.margin]="'0 .4ex 0 1ex'">
</kendo-dropdownlist>
</ng-template>
</li>
</ul>
</div>
</div>
`, isInline: true, dependencies: [{ kind: "component", type: LabelComponent, selector: "kendo-label", inputs: ["text", "for", "optional", "labelCssStyle", "labelCssClass"], exportAs: ["kendoLabel"] }, { kind: "directive", type: RepeatOnRadioButtonDirective, selector: "[kendoRecurrenceRepeatOnRadioButton]", inputs: ["kendoRecurrenceRepeatOnRadioButton"] }, { kind: "directive", type: LabelDirective, selector: "label[for]", inputs: ["for", "labelClass"] }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: DropDownListComponent, selector: "kendo-dropdownlist", inputs: ["customIconClass", "showStickyHeader", "icon", "svgIcon", "loading", "data", "value", "textField", "valueField", "adaptiveMode", "title", "subtitle", "popupSettings", "listHeight", "defaultItem", "disabled", "itemDisabled", "readonly", "filterable", "virtual", "ignoreCase", "delay", "valuePrimitive", "tabindex", "tabIndex", "size", "rounded", "fillMode", "leftRightArrowsNavigation", "id"], outputs: ["valueChange", "filterChange", "selectionChange", "open", "opened", "close", "closed", "focus", "blur"], exportAs: ["kendoDropDownList"] }, { kind: "component", type: NumericTextBoxComponent, selector: "kendo-numerictextbox", inputs: ["focusableId", "disabled", "readonly", "title", "autoCorrect", "format", "max", "min", "decimals", "placeholder", "step", "spinners", "rangeValidation", "tabindex", "tabIndex", "changeValueOnScroll", "selectOnFocus", "value", "maxlength", "size", "rounded", "fillMode", "inputAttributes"], outputs: ["valueChange", "focus", "blur", "inputFocus", "inputBlur"], exportAs: ["kendoNumericTextBox"] }, { kind: "component", type: NumericTextBoxCustomMessagesComponent, selector: "kendo-numerictextbox-messages" }] });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: RecurrenceMonthlyYearlyEditorComponent, decorators: [{
type: Component,
args: [{
selector: 'kendo-recurrence-monthly-yearly-editor',
template: `
<div class='k-form-field'>
<kendo-label
[text]="textForRepeatOn()"
labelCssClass="k-form-label"
(click)="onRepeatOnLabelClick()"
></kendo-label>
<div class="k-form-field-wrap">
<ul class='k-radio-list'>
<li class='k-radio-list-item'>
<span class="k-radio-wrap">
<input kendoRecurrenceRepeatOnRadioButton='monthday-{{uniqueId}}' />
</span>
<label [labelClass]="false" class='k-radio-label' for='k-repeaton-monthday-{{uniqueId}}'>
<ng-template [ngIf]="currentFreq === 'monthly'">
{{ textFor('monthlyDay') }}
</ng-template>
</label>
<ng-template [ngIf]="currentFreq === 'yearly'">
<kendo-dropdownlist
[data]='months'
textField='text'
valueField='value'
[value]='currentMonthMonthDay'
[valuePrimitive]='true'
(valueChange)="onMonthChange($event, 'monthday')"
[disabled]="isDisabled('monthday')"
[style.width.px]="170"
[style.margin]="'0 .4ex 0 1ex'">
</kendo-dropdownlist>
</ng-template>
<kendo-numerictextbox
class="k-recur-monthday"
[min]="numericOptions.min"
[max]="numericOptions.max"
[decimals]="0"
[format]="numericOptions.format"
[autoCorrect]="numericOptions.autoCorrect"
[readonly]="numericOptions.readonly"
[selectOnFocus]="numericOptions.selectOnFocus"
[spinners]="numericOptions.spinners"
[step]="numericOptions.step"
[title]="numericOptions.title"
[value]='monthDay'
(valueChange)='onMonthDayChange($event)'
[disabled]="isDisabled('monthday')"
>
<kendo-numerictextbox-messages
[increment]="textFor('numericIncrement')"
[decrement]="textFor('numericDecrement')"
>
</kendo-numerictextbox-messages>
</kendo-numerictextbox>
</li>
<li class='k-radio-list-item'>
<span class="k-radio-wrap">
<input kendoRecurrenceRepeatOnRadioButton='weekday-{{uniqueId}}' />
</span>
<label [labelClass]="false" class='k-radio-label' for='k-repeaton-weekday-{{uniqueId}}'></label>
<kendo-dropdownlist
[data]='offsetPositions'
textField='text'
valueField='value'
[value]='offset'
[valuePrimitive]='true'
(valueChange)='onOffsetPositionChange($event)'
[disabled]="isDisabled('weekday')"
[style.margin]="'0 .4ex 0 1ex'">
</kendo-dropdownlist>
<kendo-dropdownlist
[data]="extendedWeekDays"
textField='text'
valueField='value'
[value]='weekDay'
[valuePrimitive]='true'
(valueChange)='onWeekDayChange($event)'
[disabled]="isDisabled('weekday')"
[style.margin]="'0 .4ex 0 1ex'">
</kendo-dropdownlist>
<ng-template [ngIf]="currentFreq === 'yearly'">
<span>{{ textFor('yearlyOf') }}</span>
<kendo-dropdownlist
[data]='months'
textField='text'
valueField='value'
[value]='currentMonthWeekDay'
[valuePrimitive]='true'
(valueChange)="onMonthChange($event, 'weekday')"
[disabled]="isDisabled('weekday')"
[style.margin]="'0 .4ex 0 1ex'">
</kendo-dropdownlist>
</ng-template>
</li>
</ul>
</div>
</div>
`,
standalone: true,
imports: [LabelComponent, RepeatOnRadioButtonDirective, LabelDirective, NgIf, DropDownListComponent, NumericTextBoxComponent, NumericTextBoxCustomMessagesComponent]
}]
}], ctorParameters: function () { return [{ type: i1.RecurrenceService }, { type: i2.LocalizationService }]; }, propDecorators: { userNumericOptions: [{
type: Input
}], repeatOnRadioButtons: [{
type: ViewChildren,
args: [RepeatOnRadioButtonDirective]
}] } });