Skip to content

Commit 22f9e5f

Browse files
Scheduler - Hide days in week/month: write demo (#33318)
1 parent 8809579 commit 22f9e5f

27 files changed

+1286
-0
lines changed
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
.hidden-days-demo {
2+
display: flex;
3+
gap: 20px;
4+
}
5+
6+
.scheduler-container {
7+
flex: 1;
8+
min-width: 0;
9+
}
10+
11+
.options {
12+
display: flex;
13+
flex-direction: column;
14+
flex-shrink: 0;
15+
width: 220px;
16+
box-sizing: border-box;
17+
padding: 20px;
18+
background-color: rgba(191, 191, 191, 0.15);
19+
gap: 12px;
20+
}
21+
22+
.caption {
23+
font-weight: 500;
24+
font-size: 18px;
25+
}
26+
27+
.option {
28+
display: flex;
29+
flex-direction: column;
30+
}
31+
32+
.validation-message {
33+
display: none;
34+
margin-top: 8px;
35+
padding: 10px 12px;
36+
background: #fdf3f4;
37+
border-left: 3px solid #c50f1f;
38+
border-radius: 4px;
39+
color: #c50f1f;
40+
font-size: 13px;
41+
line-height: 1.4;
42+
}
43+
44+
::ng-deep .hidden-days-demo.is-invalid .validation-message {
45+
display: block;
46+
}
47+
48+
::ng-deep .hidden-days-demo.is-invalid .option .dx-checkbox-icon {
49+
border-color: #c50f1f;
50+
}
51+
52+
::ng-deep .hidden-days-demo.is-invalid .dx-scheduler-work-space {
53+
opacity: 0.4;
54+
pointer-events: none;
55+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<div class="hidden-days-demo" [class.is-invalid]="isInvalid">
2+
<div class="scheduler-container">
3+
<dx-scheduler
4+
[dataSource]="dataSource"
5+
[views]="['week', 'workWeek', 'month', 'timelineWeek', 'agenda']"
6+
[hiddenWeekDays]="hiddenWeekDays"
7+
currentView="week"
8+
[currentDate]="currentDate"
9+
timeZone="America/Los_Angeles"
10+
[startDayHour]="9"
11+
[height]="730"
12+
>
13+
</dx-scheduler>
14+
</div>
15+
16+
<div class="options">
17+
<div class="caption">Visible Week Days</div>
18+
@for (day of dayLabels; track day.index) {
19+
<div class="option">
20+
<dx-check-box
21+
[text]="day.label"
22+
[value]="day.visible"
23+
(onValueChanged)="onDayToggled($event, day.index)"
24+
>
25+
</dx-check-box>
26+
</div>
27+
}
28+
<div class="validation-message">
29+
{{ validationMessage }}
30+
</div>
31+
</div>
32+
</div>
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import { bootstrapApplication } from '@angular/platform-browser';
2+
import { Component, enableProdMode, provideZoneChangeDetection } from '@angular/core';
3+
import { DxSchedulerModule, DxSchedulerTypes } from 'devextreme-angular/ui/scheduler';
4+
import { DxCheckBoxModule, DxCheckBoxTypes } from 'devextreme-angular/ui/check-box';
5+
import { ArrayStore } from 'devextreme-angular/common/data';
6+
import { DataService } from './app.service';
7+
8+
if (!/localhost/.test(document.location.host)) {
9+
enableProdMode();
10+
}
11+
12+
let modulePrefix = '';
13+
// @ts-ignore
14+
if (window && window.config?.packageConfigPaths) {
15+
modulePrefix = '/app';
16+
}
17+
18+
interface DayLabel {
19+
index: DxSchedulerTypes.DayOfWeek;
20+
label: string;
21+
visible: boolean;
22+
}
23+
24+
@Component({
25+
selector: 'demo-app',
26+
templateUrl: `.${modulePrefix}/app.component.html`,
27+
styleUrls: [`.${modulePrefix}/app.component.css`],
28+
providers: [DataService],
29+
imports: [
30+
DxSchedulerModule,
31+
DxCheckBoxModule,
32+
],
33+
})
34+
export class AppComponent {
35+
dataSource: ArrayStore;
36+
37+
currentDate = new Date(2021, 3, 26);
38+
39+
validationMessage = 'The hiddenWeekDays option cannot hide all days of the week. At least one day must remain visible.';
40+
41+
dayLabels: DayLabel[] = [
42+
{ index: 0, label: 'Sunday', visible: true },
43+
{ index: 1, label: 'Monday', visible: true },
44+
{ index: 2, label: 'Tuesday', visible: true },
45+
{ index: 3, label: 'Wednesday', visible: false },
46+
{ index: 4, label: 'Thursday', visible: true },
47+
{ index: 5, label: 'Friday', visible: false },
48+
{ index: 6, label: 'Saturday', visible: true },
49+
];
50+
51+
hiddenWeekDays: DxSchedulerTypes.DayOfWeek[] = [];
52+
53+
isInvalid = false;
54+
55+
constructor(dataService: DataService) {
56+
this.dataSource = new ArrayStore({
57+
key: 'id',
58+
data: dataService.getAppointments(),
59+
});
60+
this.hiddenWeekDays = this.computeHiddenWeekDays();
61+
}
62+
63+
onDayToggled(e: DxCheckBoxTypes.ValueChangedEvent, dayIndex: number): void {
64+
this.dayLabels[dayIndex].visible = e.value;
65+
this.isInvalid = this.dayLabels.every((d) => !d.visible);
66+
this.hiddenWeekDays = this.computeHiddenWeekDays();
67+
}
68+
69+
private computeHiddenWeekDays(): DxSchedulerTypes.DayOfWeek[] {
70+
return this.dayLabels
71+
.filter((d) => !d.visible)
72+
.map((d) => d.index);
73+
}
74+
}
75+
76+
bootstrapApplication(AppComponent, {
77+
providers: [
78+
provideZoneChangeDetection({ eventCoalescing: true, runCoalescing: true }),
79+
],
80+
});
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
import { Injectable } from '@angular/core';
2+
3+
export class Appointment {
4+
id: number;
5+
6+
text: string;
7+
8+
startDate: Date;
9+
10+
endDate: Date;
11+
12+
allDay?: boolean;
13+
}
14+
15+
const appointments: Appointment[] = [
16+
{
17+
id: 1,
18+
text: 'Website Re-Design Plan',
19+
startDate: new Date('2021-04-26T16:30:00.000Z'),
20+
endDate: new Date('2021-04-26T18:30:00.000Z'),
21+
},
22+
{
23+
id: 2,
24+
text: 'Book Flights to San Fran for Sales Trip',
25+
startDate: new Date('2021-04-26T19:00:00.000Z'),
26+
endDate: new Date('2021-04-26T20:00:00.000Z'),
27+
allDay: true,
28+
},
29+
{
30+
id: 3,
31+
text: 'Install New Router in Dev Room',
32+
startDate: new Date('2021-04-26T21:30:00.000Z'),
33+
endDate: new Date('2021-04-26T22:30:00.000Z'),
34+
},
35+
{
36+
id: 4,
37+
text: 'Approve Personal Computer Upgrade Plan',
38+
startDate: new Date('2021-04-27T17:00:00.000Z'),
39+
endDate: new Date('2021-04-27T18:00:00.000Z'),
40+
},
41+
{
42+
id: 5,
43+
text: 'Final Budget Review',
44+
startDate: new Date('2021-04-27T19:00:00.000Z'),
45+
endDate: new Date('2021-04-27T20:35:00.000Z'),
46+
},
47+
{
48+
id: 6,
49+
text: 'New Brochures',
50+
startDate: new Date('2021-04-27T21:30:00.000Z'),
51+
endDate: new Date('2021-04-27T22:45:00.000Z'),
52+
},
53+
{
54+
id: 7,
55+
text: 'Install New Database',
56+
startDate: new Date('2021-04-28T16:45:00.000Z'),
57+
endDate: new Date('2021-04-28T18:15:00.000Z'),
58+
},
59+
{
60+
id: 8,
61+
text: 'Approve New Online Marketing Strategy',
62+
startDate: new Date('2021-04-28T19:00:00.000Z'),
63+
endDate: new Date('2021-04-28T21:00:00.000Z'),
64+
},
65+
{
66+
id: 9,
67+
text: 'Upgrade Personal Computers',
68+
startDate: new Date('2021-04-28T22:15:00.000Z'),
69+
endDate: new Date('2021-04-28T23:30:00.000Z'),
70+
},
71+
{
72+
id: 10,
73+
text: 'Customer Workshop',
74+
startDate: new Date('2021-04-29T18:00:00.000Z'),
75+
endDate: new Date('2021-04-29T19:00:00.000Z'),
76+
allDay: true,
77+
},
78+
{
79+
id: 11,
80+
text: 'Prepare 2021 Marketing Plan',
81+
startDate: new Date('2021-04-29T18:00:00.000Z'),
82+
endDate: new Date('2021-04-29T20:30:00.000Z'),
83+
},
84+
{
85+
id: 12,
86+
text: 'Brochure Design Review',
87+
startDate: new Date('2021-04-29T21:00:00.000Z'),
88+
endDate: new Date('2021-04-29T22:30:00.000Z'),
89+
},
90+
{
91+
id: 13,
92+
text: 'Create Icons for Website',
93+
startDate: new Date('2021-04-30T17:00:00.000Z'),
94+
endDate: new Date('2021-04-30T18:30:00.000Z'),
95+
},
96+
{
97+
id: 14,
98+
text: 'Upgrade Server Hardware',
99+
startDate: new Date('2021-04-30T21:30:00.000Z'),
100+
endDate: new Date('2021-04-30T23:00:00.000Z'),
101+
},
102+
{
103+
id: 15,
104+
text: 'Submit New Website Design',
105+
startDate: new Date('2021-04-30T23:30:00.000Z'),
106+
endDate: new Date('2021-05-01T01:00:00.000Z'),
107+
},
108+
{
109+
id: 16,
110+
text: 'Launch New Website',
111+
startDate: new Date('2021-04-30T19:20:00.000Z'),
112+
endDate: new Date('2021-04-30T21:00:00.000Z'),
113+
},
114+
];
115+
116+
@Injectable()
117+
export class DataService {
118+
getAppointments(): Appointment[] {
119+
return appointments;
120+
}
121+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<!DOCTYPE html>
2+
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
3+
<head>
4+
<title>DevExtreme Demo</title>
5+
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
6+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
7+
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0" />
8+
<link rel="stylesheet" type="text/css" href="../../../../node_modules/devextreme-dist/css/dx.light.css" />
9+
10+
<script src="../../../../node_modules/core-js/client/shim.min.js"></script>
11+
<script src="../../../../node_modules/zone.js/bundles/zone.umd.js"></script>
12+
<script src="../../../../node_modules/reflect-metadata/Reflect.js"></script>
13+
<script src="../../../../node_modules/systemjs/dist/system.js"></script>
14+
15+
<script src="config.js"></script>
16+
<script>
17+
System.import("app").catch(console.error.bind(console));
18+
</script>
19+
</head>
20+
21+
<body class="dx-viewport">
22+
<div class="demo-container">
23+
<demo-app>Loading...</demo-app>
24+
</div>
25+
</body>
26+
</html>
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import React, { useCallback, useMemo, useState } from 'react';
2+
3+
import Scheduler, { type SchedulerTypes } from 'devextreme-react/scheduler';
4+
import CheckBox, { type CheckBoxTypes } from 'devextreme-react/check-box';
5+
import { ArrayStore } from 'devextreme-react/common/data';
6+
import { data } from './data.ts';
7+
8+
const dataSource = new ArrayStore({
9+
key: 'id',
10+
data,
11+
});
12+
13+
const allDays: SchedulerTypes.DayOfWeek[] = [0, 1, 2, 3, 4, 5, 6];
14+
const dayLabels = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
15+
const defaultVisible: SchedulerTypes.DayOfWeek[] = [0, 1, 2, 4, 6];
16+
const views: SchedulerTypes.Properties['views'] = ['week', 'workWeek', 'month', 'timelineWeek', 'agenda'];
17+
const currentDate = new Date(2021, 3, 26);
18+
const VALIDATION_MESSAGE = 'The hiddenWeekDays option cannot hide all days of the week. At least one day must remain visible.';
19+
20+
const App = () => {
21+
const [visibleDays, setVisibleDays] = useState<SchedulerTypes.DayOfWeek[]>(defaultVisible);
22+
23+
const isInvalid = visibleDays.length === 0;
24+
25+
const hiddenWeekDays = useMemo(
26+
() => allDays.filter((d) => !visibleDays.includes(d)),
27+
[visibleDays],
28+
);
29+
30+
const onDayToggle = useCallback((dayIndex: SchedulerTypes.DayOfWeek, e: CheckBoxTypes.ValueChangedEvent) => {
31+
setVisibleDays((prev) => (e.value
32+
? [...prev, dayIndex]
33+
: prev.filter((d) => d !== dayIndex)));
34+
}, []);
35+
36+
return (
37+
<div className={`hidden-days-demo${isInvalid ? ' is-invalid' : ''}`}>
38+
<div className="scheduler-container">
39+
<Scheduler
40+
timeZone="America/Los_Angeles"
41+
dataSource={dataSource}
42+
views={views}
43+
hiddenWeekDays={hiddenWeekDays}
44+
defaultCurrentView="week"
45+
defaultCurrentDate={currentDate}
46+
startDayHour={9}
47+
height={730}
48+
/>
49+
</div>
50+
<div className="options">
51+
<div className="caption">Visible Week Days</div>
52+
{dayLabels.map((label, idx) => (
53+
<div className="option" key={label}>
54+
<CheckBox
55+
text={label}
56+
value={visibleDays.includes(idx as SchedulerTypes.DayOfWeek)}
57+
onValueChanged={(e) => onDayToggle(idx as SchedulerTypes.DayOfWeek, e)}
58+
/>
59+
</div>
60+
))}
61+
<div className="validation-message">
62+
{VALIDATION_MESSAGE}
63+
</div>
64+
</div>
65+
</div>
66+
);
67+
};
68+
69+
export default App;

0 commit comments

Comments
 (0)