[]
        
(Showing Draft Content)

Detect and Handle Conflicts

Scheduler can detect overlapping events and events that intersect configured non-working time. Detection is informational by default. Cancel the conflictChecked event when the application must reject a conflicting operation.

Reject conflicting changes

conflictChecked runs after a valid Create or Update candidate is calculated and before it is committed. It also runs for mouse Move and Resize operations.

scheduler.conflictChecked.addHandler((_sender, args) => {
  const conflicts = args.result?.conflicts ?? [];
  if (conflicts.length > 0) {
    showConflictWarning(conflicts);
    args.cancel = true;
  }
});

Leave args.cancel unchanged when conflicts should only be displayed, logged, or sent to a review workflow. Server-side validation remains authoritative.

Need

Use

Read conflicts from a programmatic request

Inspect result.conflicts.

Reject a pending request

Set args.cancel = true in conflictChecked.

Stop before conflict detection

Set args.cancel = true in itemChanging.

Persist an accepted request

Handle itemChanged.

Read conflict results

args.result.conflicts contains zero or more conflict records. A result can contain both types.

Type

Meaning

Detail property

SchedulerConflictType.TimeOverlap

The candidate overlaps another loaded event.

conflictingItems

SchedulerConflictType.NonWorkingTime

The candidate intersects configured non-working time.

conflictingTimeRanges

Use conflict.type rather than array order when applying different business rules.

scheduler.conflictChecked.addHandler((_sender, args) => {
  for (const conflict of args.result?.conflicts ?? []) {
    if (conflict.type === wjScheduler.SchedulerConflictType.TimeOverlap) {
      notifyOverlap(conflict.conflictingItems);
    }
    if (conflict.type === wjScheduler.SchedulerConflictType.NonWorkingTime) {
      notifyUnavailable(conflict.conflictingTimeRanges);
    }
  }
});

The result is available only after the operation reaches conflict detection. It can be absent when validation fails or an earlier cancelable event stops the request.

Understand matching rules

  • Event ranges use [start, end), so adjacent events do not conflict.

  • With resources, two events conflict only when every resource field they both set has the same value.

  • Empty or unknown resource values are ignored. An empty resource data source does not participate in matching.

  • When resources are configured but neither event has a valid resource value, they do not produce a TimeOverlap conflict.

  • Working-time conflicts are global and are not filtered by resource.

  • Event overlap checks include only events currently loaded by Scheduler.

For example, with roomId as the matching resource dimension:

Event A

Event B

Time overlap conflict

09:00-10:00, Room A

10:00-11:00, Room A

No; ranges are adjacent

09:00-10:00, Room A

09:30-10:30, Room A

Yes

09:00-10:00, Room A

09:30-10:30, Room B

No; resource values differ

With multiple resource fields, every field that both events set must match. For example, an overlap matches only when both teamId and regionId match; a different value in either field prevents a TimeOverlap conflict.

Resource configuration

Event A

Event B

Time-overlap result

No resources configured

No assignment

No assignment

Time overlap is reported.

Resources configured

No valid assignment

No valid assignment

No TimeOverlap is reported.

Resources configured

team=A, region=East

team=A, region=East

Time overlap is reported.

Resources configured

team=A, region=East

team=A, region=West

No TimeOverlap; a resource value differs.

Inspect conflicts from an update result

When application code calls an update method, inspect the returned result after the operation reaches validation and conflict detection.

const event = scheduler.getEvents(undefined, undefined, [
  { fieldExpr: 'id', value: 1 },
])[0];

if (event) {
  const result = scheduler.update(event, {
    start: new Date(2026, 7, 24, 9, 30),
    end: new Date(2026, 7, 24, 10, 30),
  });
  const conflicts = result.conflicts ?? [];
}

The item passed to update must be the original object reference from the current Scheduler collection. Do not pass a copy, a rendered event instance, or an item from another collection. Use the event handler when the application must cancel the operation; use the returned result to display or log a programmatic request.


The returned result reports the outcome of the programmatic request; it does not replace cancellation in conflictChecked. A request canceled by itemChanging may not reach conflict detection and may therefore have no conflict result.

Style conflicting events

Scheduler applies wj-scheduler-item-conflict to an event with one or more conflicts.

.wj-scheduler-item-conflict {
  outline: 2px solid #dc2626;
  outline-offset: -2px;
}

Custom item templates can read SchedulerItemTemplateContext.conflicts and render details based on each conflict's type. Keep conflict presentation separate from the source item data.