diff --git a/apps/demos/Demos/Scheduler/ResolveTimeConflicts/Angular/app/app.component.html b/apps/demos/Demos/Scheduler/ResolveTimeConflicts/Angular/app/app.component.html
index 5d72aef3ca89..d65ccc55673b 100644
--- a/apps/demos/Demos/Scheduler/ResolveTimeConflicts/Angular/app/app.component.html
+++ b/apps/demos/Demos/Scheduler/ResolveTimeConflicts/Angular/app/app.component.html
@@ -70,7 +70,7 @@
-
Overlapping Rule
+
Allow Overlapping Appointments
{
formRef.current?.option('elementAttr.class', show ? '' : 'hide-informer');
}, []);
- const alertConflictIfNeeded = useCallback((
+ const handleConflict = useCallback((
e: SchedulerTypes.AppointmentAddingEvent | SchedulerTypes.AppointmentUpdatingEvent,
appointmentData: Appointment,
) => {
@@ -144,12 +144,12 @@ const App = () => {
}, [setConflictError]);
const onAppointmentAdding = useCallback((e: SchedulerTypes.AppointmentAddingEvent) => {
- alertConflictIfNeeded(e, e.appointmentData as Appointment);
- }, [alertConflictIfNeeded]);
+ handleConflict(e, e.appointmentData as Appointment);
+ }, [handleConflict]);
const onAppointmentUpdating = useCallback((e: SchedulerTypes.AppointmentUpdatingEvent) => {
- alertConflictIfNeeded(e, { ...e.oldData, ...e.newData } as Appointment);
- }, [alertConflictIfNeeded]);
+ handleConflict(e, { ...e.oldData, ...e.newData } as Appointment);
+ }, [handleConflict]);
const popupOptions = useMemo(() => ({
onInitialized: (e: PopupTypes.InitializedEvent) => {
@@ -254,7 +254,7 @@ const App = () => {
-
Overlapping Rule
+
Allow Overlapping Appointments
{
showConflictErrorRef.current = show;
formRef.current?.option('elementAttr.class', show ? '' : 'hide-informer');
}, []);
- const alertConflictIfNeeded = useCallback(
+ const handleConflict = useCallback(
(e, appointmentData) => {
if (!detectConflict(e.component, appointmentData, overlappingRuleRef.current)) {
setConflictError(false);
@@ -113,15 +113,15 @@ const App = () => {
);
const onAppointmentAdding = useCallback(
(e) => {
- alertConflictIfNeeded(e, e.appointmentData);
+ handleConflict(e, e.appointmentData);
},
- [alertConflictIfNeeded],
+ [handleConflict],
);
const onAppointmentUpdating = useCallback(
(e) => {
- alertConflictIfNeeded(e, { ...e.oldData, ...e.newData });
+ handleConflict(e, { ...e.oldData, ...e.newData });
},
- [alertConflictIfNeeded],
+ [handleConflict],
);
const popupOptions = useMemo(
() => ({
@@ -238,7 +238,7 @@ const App = () => {
-
Overlapping Rule
+
Allow Overlapping Appointments
-
Overlapping Rule
+
Allow Overlapping Appointments
{
@@ -221,11 +221,11 @@ const alertConflictIfNeeded = (
};
const onAppointmentAdding = (e: DxSchedulerTypes.AppointmentAddingEvent) => {
- alertConflictIfNeeded(e, e.appointmentData as Appointment);
+ handleConflict(e, e.appointmentData as Appointment);
};
const onAppointmentUpdating = (e: DxSchedulerTypes.AppointmentUpdatingEvent) => {
- alertConflictIfNeeded(e, { ...e.oldData, ...e.newData } as Appointment);
+ handleConflict(e, { ...e.oldData, ...e.newData } as Appointment);
};
const onFormInitialized = (e: DxFormTypes.InitializedEvent) => {
diff --git a/apps/demos/Demos/Scheduler/ResolveTimeConflicts/description.md b/apps/demos/Demos/Scheduler/ResolveTimeConflicts/description.md
new file mode 100644
index 000000000000..f0982a91a1f2
--- /dev/null
+++ b/apps/demos/Demos/Scheduler/ResolveTimeConflicts/description.md
@@ -0,0 +1,26 @@
+This example prevents appointment time conflicts in DevExtreme Scheduler. Use the **Allow Overlapping Appointments** select-box to select a time conflict resolution mode.
+
+
+### Detect Conflicts
+
+Handle the [onAppointmentAdding](/Documentation/ApiReference/UI_Components/dxScheduler/Configuration/#onAppointmentAdding) and [onAppointmentUpdating](/Documentation/ApiReference/UI_Components/dxScheduler/Configuration/#onAppointmentUpdating) events to check if a new or updated appointment creates a time conflict. Set `e.cancel = true` to block the operation if necessary.
+
+Call [getOccurrences](/Documentation/ApiReference/UI_Components/dxScheduler/Methods/#getOccurrences) to expand [recurring appointments](/Documentation/Guide/UI_Components/Scheduler/Appointments/Appointment_Types/#Recurring_Appointments) into individual occurrences within the target range. Check for overlapping time ranges.
+
+### Conflict Detection Modes
+
+The demo supports two modes:
+
+- **Different resources**: appointments assigned to different resources (assignees) can overlap.
+- **Never**: overlapping appointments are not allowed, regardless of resource assignment.
+
+To implement resource-aware checks, access appointments and compare their `assigneeId` field values.
+
+### Display Errors
+
+When a conflict is detected, the demo displays the error in the following ways:
+
+- A message box.
+- An inline validation message (if an appointment edit form is active).
+
+To display inline validation, use the `customizeItem` function to add a custom form item inside [editing.form](/Documentation/ApiReference/UI_Components/dxScheduler/Configuration/editing/form/) and attach custom `validationRules` to time editors.
\ No newline at end of file
diff --git a/apps/demos/Demos/Scheduler/ResolveTimeConflicts/jQuery/index.html b/apps/demos/Demos/Scheduler/ResolveTimeConflicts/jQuery/index.html
index 515568bf97e7..6caac5df7604 100644
--- a/apps/demos/Demos/Scheduler/ResolveTimeConflicts/jQuery/index.html
+++ b/apps/demos/Demos/Scheduler/ResolveTimeConflicts/jQuery/index.html
@@ -18,7 +18,7 @@
-
Overlapping Rule
+
Allow Overlapping Appointments
diff --git a/apps/demos/Demos/Scheduler/ResolveTimeConflicts/jQuery/index.js b/apps/demos/Demos/Scheduler/ResolveTimeConflicts/jQuery/index.js
index 7b07dd1a5189..b6a6887daf51 100644
--- a/apps/demos/Demos/Scheduler/ResolveTimeConflicts/jQuery/index.js
+++ b/apps/demos/Demos/Scheduler/ResolveTimeConflicts/jQuery/index.js
@@ -109,10 +109,10 @@ $(() => {
},
},
onAppointmentAdding(e) {
- alertConflictIfNeeded(e, e.appointmentData);
+ handleConflict(e, e.appointmentData);
},
onAppointmentUpdating(e) {
- alertConflictIfNeeded(e, e.newData);
+ handleConflict(e, e.newData);
},
}).dxScheduler('instance');
@@ -121,7 +121,7 @@ $(() => {
form?.option('elementAttr.class', show ? '' : 'hide-informer');
}
- function alertConflictIfNeeded(e, appointmentData) {
+ function handleConflict(e, appointmentData) {
if (!detectConflict(appointmentData)) {
setConflictError(false);
return;
@@ -198,8 +198,8 @@ $(() => {
$('#overlapping-rule').dxSelectBox({
items: [
- { value: 'sameResource', text: 'Allow across resources' },
- { value: 'allResources', text: 'Disallow all overlaps' },
+ { value: 'sameResource', text: 'Different Resources' },
+ { value: 'allResources', text: 'Never' },
],
valueExpr: 'value',
displayExpr: 'text',