Skip to content

Scheduler: Appointment form customization#31555

Merged
alexslavr merged 14 commits into
DevExpress:25_2from
aleksei-semikozov:form-options
Nov 18, 2025
Merged

Scheduler: Appointment form customization#31555
alexslavr merged 14 commits into
DevExpress:25_2from
aleksei-semikozov:form-options

Conversation

@aleksei-semikozov

Copy link
Copy Markdown
Contributor

No description provided.

@aleksei-semikozov aleksei-semikozov self-assigned this Nov 3, 2025
@aleksei-semikozov aleksei-semikozov requested a review from a team as a code owner November 3, 2025 07:05
@aleksei-semikozov aleksei-semikozov requested review from a team and Copilot November 3, 2025 07:05

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR enables propagating all dxForm options to the Scheduler's appointment form by extending the editing.form configuration to accept all dxForm properties. Previously, only a limited subset of properties (items, onSaved, onCanceled, iconsShowMode) were supported.

Key Changes

  • Extended editing.form type definition to include all dxFormProperties/dxFormOptions
  • Spread user form options into the form initialization using spread operator
  • Updated wrapper packages (Angular, React, Vue) to include all form properties and events
  • Added test coverage to verify form options are properly propagated

Reviewed Changes

Copilot reviewed 7 out of 9 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
packages/devextreme/ts/dx.all.d.ts Updated type definition to extend dxForm.Properties instead of defining limited properties
packages/devextreme/js/ui/scheduler.d.ts Changed type from inline object to FormProperties with additional scheduler-specific properties
packages/devextreme/js/__internal/scheduler/appointment_popup/m_form.ts Spread userFormOptions into form initialization to propagate all dxForm options
packages/devextreme/js/__internal/scheduler/appointment_popup/appointment_popup.test.ts Added test case to verify form options propagation
packages/devextreme-vue/src/scheduler.ts Regenerated wrapper to include all dxForm properties, events, and imports
packages/devextreme-react/src/scheduler.ts Regenerated wrapper to include all dxForm properties, events, and subscribable options
packages/devextreme-angular/src/ui/scheduler/nested/form.ts Regenerated nested component with all dxForm input/output properties
packages/devextreme-angular/src/ui/scheduler/nested/editing.ts Updated form type to use dxFormOptions
packages/devextreme-angular/src/ui/scheduler/index.ts Updated editing property type to use dxFormOptions

Comment thread packages/devextreme/js/__internal/scheduler/appointment_popup/m_form.ts Outdated
Comment thread packages/devextreme/js/__internal/scheduler/appointment_popup/m_form.ts Outdated
Comment thread packages/devextreme/js/__internal/scheduler/appointment_popup/m_form.ts Outdated
Copilot AI review requested due to automatic review settings November 5, 2025 01:57

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 7 out of 9 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (2)

packages/devextreme/js/__internal/scheduler/appointment_popup/m_form.ts:226

  • The spread of userFormOptions occurs after all internal configuration options (line 262), which means user-provided values could override critical internal options like items, formData, onFieldDataChanged, and onInitialized. These handlers are essential for scheduler functionality (managing recurrence form, date editor updates, resource icon colors). Consider spreading userFormOptions before the critical internal options to prevent users from accidentally breaking scheduler behavior, or explicitly exclude certain properties from being overridden.
    return this.scheduler.createComponent(element, dxForm, {
      items,
      formData: {},
      showColonAfterLabel: false,
      showValidationSummary: false,
      scrollingEnabled: false,
      labelLocation: 'top',
      colCountByScreen: {
        xs: 1,
      },
      elementAttr: {
        class: CLASSES.form,
      },
      onFieldDataChanged: (e) => {

packages/devextreme-angular/src/ui/scheduler/nested/form.ts:1

  • Adding two-way binding support for formData in the nested form component is problematic. The form's formData is managed internally by the scheduler and updated dynamically during appointment editing. Exposing it as a bindable property could lead to conflicts where user updates compete with internal scheduler updates, potentially causing data synchronization issues or breaking appointment editing functionality.
/* tslint:disable:max-line-length */

), []);

const subscribableOptions = useMemo(() => (["currentDate","currentView"]), []);
const subscribableOptions = useMemo(() => (["currentDate","currentView","editing.form.formData"]), []);

Copilot AI Nov 5, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding 'editing.form.formData' to subscribableOptions appears incorrect. The formData property is an internal form property that gets updated dynamically as users edit appointment fields, not a scheduler option that should trigger re-renders. This could cause unnecessary re-renders or synchronization issues. The scheduler manages form data internally through createForm, and users shouldn't be subscribing to this nested path.

Suggested change
const subscribableOptions = useMemo(() => (["currentDate","currentView","editing.form.formData"]), []);
const subscribableOptions = useMemo(() => (["currentDate","currentView"]), []);

Copilot uses AI. Check for mistakes.
Comment thread packages/devextreme-react/src/scheduler.ts Outdated
Comment thread packages/devextreme/js/__internal/scheduler/appointment_popup/m_form.ts Outdated
Copilot AI review requested due to automatic review settings November 6, 2025 14:08
@aleksei-semikozov aleksei-semikozov force-pushed the form-options branch 2 times, most recently from 1862952 to 61488df Compare November 6, 2025 14:11

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 7 out of 9 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (2)

packages/devextreme/js/__internal/scheduler/appointment_popup/m_form.ts:263

  • Deep merge with extend(true, ...) will merge the onInitialized and onFieldDataChanged callbacks from defaultOptions and customFormOptions, potentially causing issues. If a user provides these callbacks in customFormOptions, both callbacks would be merged (object merge), not executed in sequence. You should handle these lifecycle callbacks specially - either by wrapping them to call both, or by ensuring custom callbacks take precedence while preserving the default behavior. For example, save references to default handlers and conditionally chain them.
          return;

packages/devextreme/js/__internal/scheduler/appointment_popup/m_form.ts:211

  • When editingConfig is a boolean (e.g., editing: true), editingConfig.form will be undefined and default to {}. However, consider checking isBoolean(editingConfig) here for clarity and consistency with the existing getIconsShowMode() method pattern on line 201.
    const recurrenceGroup = this._recurrenceForm.createRecurrenceFormGroup();

aleksei-semikozov and others added 3 commits November 7, 2025 12:14
…appointment_popup.test.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Aleksei Semikozov <alwexy@gmail.com>
Copilot AI review requested due to automatic review settings November 7, 2025 15:42

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 7 out of 9 changed files in this pull request and generated 1 comment.

Comment thread packages/devextreme/js/__internal/scheduler/appointment_popup/m_form.ts Outdated
Comment thread packages/devextreme/js/__internal/scheduler/appointment_popup/m_form.ts Outdated
Copilot AI review requested due to automatic review settings November 10, 2025 13:32

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 31 out of 34 changed files in this pull request and generated no new comments.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 31 out of 34 changed files in this pull request and generated 2 comments.

Comment on lines +244 to 245
const defaultOptions: FormProperties = {
items,

Copilot AI Nov 12, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The items parameter is used for default options, but formItems from custom config is destructured and ignored. This could lead to confusion about which items are actually used. Consider documenting this behavior or renaming to clarify that custom items should be part of customFormOptions.

Copilot uses AI. Check for mistakes.
} as FormProperties) as dxForm;
} as FormProperties;

const formOptions = extend(true, defaultOptions, customFormOptions);

Copilot AI Nov 12, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Add a comment explaining that deep merge is intentional here to allow partial overrides of nested options like elementAttr while preserving default values for non-specified properties.

Copilot uses AI. Check for mistakes.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 30 out of 33 changed files in this pull request and generated 3 comments.

allowTimeZoneEditing: Boolean,
allowUpdating: Boolean,
form: Object as PropType<Record<string, any>>,
form: {},

Copilot AI Nov 13, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The type of the form prop has been changed from a specific typed object to an empty object literal {}. This loses type safety and makes it harder for developers to discover what properties are available. Consider using Object as PropType<Record<string, any>> to maintain consistency with other similar props in the file (like line 403 for popup), or better yet, importing and using the proper SchedulerAppointmentFormOptions type.

Suggested change
form: {},
form: Object as PropType<Record<string, any>>,

Copilot uses AI. Check for mistakes.
onCanceled?: ((formData: any) => void);
onSaved?: ((formData: any) => void);
};
form?: any;

Copilot AI Nov 13, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The type of the form property has been changed to any, which eliminates type safety. This is inconsistent with the approach in the TypeScript definitions where a proper SchedulerAppointmentFormOptions type was created. Consider importing and using the proper type from devextreme/ui/scheduler to maintain type safety and IntelliSense support for developers.

Copilot uses AI. Check for mistakes.
Comment on lines +83 to +86
get form(): any {
return this._getOption('form');
}
set form(value: undefined | { iconsShowMode?: AppointmentFormIconsShowMode, items?: Array<dxFormButtonItem | dxFormEmptyItem | dxFormGroupItem | dxFormSimpleItem | dxFormTabbedItem>, onCanceled?: ((formData: any) => void), onSaved?: ((formData: any) => void) }) {
set form(value: any) {

Copilot AI Nov 13, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The form property type has been changed from a specific typed object to any, losing type safety. Similar to the React and Vue wrappers, this should use the proper SchedulerAppointmentFormOptions type from devextreme/ui/scheduler to maintain type safety and developer experience consistency across all framework wrappers.

Copilot uses AI. Check for mistakes.
Copilot AI review requested due to automatic review settings November 17, 2025 14:54

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Comment thread packages/devextreme/js/ui/scheduler.d.ts Outdated
@alexslavr alexslavr merged commit 39a0903 into DevExpress:25_2 Nov 18, 2025
105 of 122 checks passed
@aleksei-semikozov aleksei-semikozov deleted the form-options branch March 20, 2026 17:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants