Skip to content

Commit 2e30555

Browse files
Merge branch '25_2' into 25_2_upd_apps_angular_to_ng19
2 parents 99e5627 + 5aff64a commit 2e30555

File tree

10 files changed

+303
-104
lines changed

10 files changed

+303
-104
lines changed

apps/demos/Demos/Scheduler/Templates/Angular/app/app.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ <h3>DXCinema Show Times</h3>
123123
<div class="title">{{ movie.text }}</div>
124124
<div>
125125
Ticket Price:
126-
<strong>${{ model.targetedAppointmentData.price }}</strong>
126+
<strong>$ {{ model.targetedAppointmentData.price }}</strong>
127127
</div>
128128
<div>
129129
{{

apps/demos/Demos/Scheduler/Templates/Angular/app/app.component.ts

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,17 @@ import {
33
} from '@angular/core';
44
import { BrowserModule } from '@angular/platform-browser';
55
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
6-
import query from 'devextreme/data/query';
6+
import { query } from 'devextreme-angular/common/data';
77
import { DxSchedulerModule, DxSchedulerComponent } from 'devextreme-angular/ui/scheduler';
8-
import {
9-
ValueChangedEvent as SelectBoxValueChangedEvent,
10-
ContentReadyEvent as SelectBoxContentReadyEvent,
11-
} from 'devextreme/ui/select_box';
12-
import dxForm, {
13-
InitializedEvent as FormInitializedEvent,
14-
FieldDataChangedEvent,
15-
} from 'devextreme/ui/form';
16-
import { OptionChangedEvent as PopupOptionChangedEvent } from 'devextreme/ui/popup';
8+
import { DxSelectBoxTypes } from 'devextreme-angular/ui/select-box';
9+
import { DxFormTypes } from 'devextreme-angular/ui/form';
10+
import { DxPopupTypes } from 'devextreme-angular/ui/popup';
1711
import {
1812
Service, MovieData, TheatreData, Data,
1913
} from './app.service';
2014

15+
type dxForm = NonNullable<DxFormTypes.InitializedEvent['component']>;
16+
2117
@Pipe({ name: 'apply' })
2218
export class ApplyPipe<TArgs, TReturn> implements PipeTransform {
2319
transform(func: ((...args: TArgs[]) => TReturn), ...args: TArgs[]): TReturn { return func(...args); }
@@ -69,7 +65,7 @@ export class AppComponent {
6965

7066
priceDisplayExpr = (value: number): string => `$${value}`;
7167

72-
onMovieValueChanged = (e: SelectBoxValueChangedEvent): void => {
68+
onMovieValueChanged = (e: DxSelectBoxTypes.ValueChangedEvent): void => {
7369
const movie = this.getMovieById(e.value);
7470
this.currentSelectedMovie = movie;
7571

@@ -79,15 +75,15 @@ export class AppComponent {
7975
}
8076
};
8177

82-
onMovieEditorContentReady = (e: SelectBoxContentReadyEvent): void => {
78+
onMovieEditorContentReady = (e: DxSelectBoxTypes.ContentReadyEvent): void => {
8379
e.component.option('stylingMode', this.getEditorStylingMode());
8480
};
8581

86-
onPriceEditorContentReady = (e: SelectBoxContentReadyEvent): void => {
82+
onPriceEditorContentReady = (e: DxSelectBoxTypes.ContentReadyEvent): void => {
8783
e.component.option('stylingMode', this.getEditorStylingMode());
8884
};
8985

90-
onPopupOptionChanged = (e: PopupOptionChangedEvent): void => {
86+
onPopupOptionChanged = (e: DxPopupTypes.OptionChangedEvent): void => {
9187
if (e.fullName === 'toolbarItems' && e.value) {
9288
e.value.forEach((item, index) => {
9389
if (item.shortcut === 'done' || item.shortcut === 'cancel') {
@@ -106,7 +102,7 @@ export class AppComponent {
106102
}
107103
};
108104

109-
onFormInitialized = (e: FormInitializedEvent): void => {
105+
onFormInitialized = (e: DxFormTypes.InitializedEvent): void => {
110106
const form = e.component;
111107
this.formInstance = form;
112108

@@ -118,7 +114,7 @@ export class AppComponent {
118114
this.currentSelectedMovie = null;
119115
}
120116

121-
form.on('fieldDataChanged', (fieldEvent: FieldDataChangedEvent) => {
117+
form.on('fieldDataChanged', (fieldEvent: DxFormTypes.FieldDataChangedEvent) => {
122118
if (fieldEvent.dataField === 'startDate') {
123119
const currentFormData = form.option('formData');
124120
if (currentFormData.movieId) {

apps/demos/Demos/Scheduler/Templates/React/App.tsx

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,17 @@ import Scheduler, {
88
} from 'devextreme-react/scheduler';
99
import { query } from 'devextreme-react/common/data';
1010
import { type SelectBoxTypes } from 'devextreme-react/select-box';
11-
import type { InitializedEvent as FormInitializedEvent, FieldDataChangedEvent } from 'devextreme/ui/form';
12-
import type dxForm from 'devextreme/ui/form';
13-
import type { OptionChangedEvent as PopupOptionChangedEvent } from 'devextreme/ui/popup';
11+
import { type FormTypes } from 'devextreme-react/form';
12+
import { type PopupTypes } from 'devextreme-react/popup';
1413
import Appointment from './Appointment.tsx';
1514
import AppointmentTooltip from './AppointmentTooltip.tsx';
1615
import MovieInfoContainer from './MovieInfoContainer.tsx';
1716
import {
1817
data, moviesData, theatreData, type MovieResource,
1918
} from './data.ts';
2019

20+
type dxForm = NonNullable<FormTypes.InitializedEvent['component']>;
21+
2122
const currentDate = new Date(2025, 3, 27);
2223
const views: SchedulerTypes.ViewType[] = ['day', 'week', 'timelineDay'];
2324
const groups = ['theatreId'];
@@ -60,7 +61,7 @@ const App = () => {
6061
e.component.option('stylingMode', getEditorStylingMode());
6162
}, []);
6263

63-
const onPopupOptionChanged = useCallback((e: PopupOptionChangedEvent) => {
64+
const onPopupOptionChanged = useCallback((e: PopupTypes.OptionChangedEvent) => {
6465
if (e.fullName === 'toolbarItems' && e.value) {
6566
e.value.forEach((item: any, index: number) => {
6667
if (item.shortcut === 'done' || item.shortcut === 'cancel') {
@@ -70,11 +71,11 @@ const App = () => {
7071
}
7172
}, []);
7273

73-
const onFormInitialized = useCallback((e: FormInitializedEvent) => {
74+
const onFormInitialized = useCallback((e: FormTypes.InitializedEvent) => {
7475
const form = e.component;
7576
formInstanceRef.current = form;
7677

77-
form.on('fieldDataChanged', (fieldEvent: FieldDataChangedEvent) => {
78+
form.on('fieldDataChanged', (fieldEvent: FormTypes.FieldDataChangedEvent) => {
7879
if (fieldEvent.dataField === 'startDate') {
7980
const currentFormData = form.option('formData');
8081
if (currentFormData.movieId) {

apps/demos/Demos/Scheduler/Templates/React/MovieInfoContainer.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import React, { useState, useEffect } from 'react';
2-
import type dxForm from 'devextreme/ui/form';
3-
import type { FieldDataChangedEvent } from 'devextreme/ui/form';
2+
import { type FormTypes } from 'devextreme-react/form';
43
import { query } from 'devextreme-react/common/data';
54
import { moviesData, type MovieResource } from './data.ts';
65

6+
type dxForm = NonNullable<FormTypes.InitializedEvent['component']>;
7+
78
type MovieInfoContainerProps = {
89
formInstanceRef: React.RefObject<dxForm | null>;
910
};
@@ -25,7 +26,7 @@ const MovieInfoContainer: React.FC<MovieInfoContainerProps> = ({ formInstanceRef
2526
setMovie(null);
2627
}
2728

28-
const handleFieldDataChanged = (e: FieldDataChangedEvent) => {
29+
const handleFieldDataChanged = (e: FormTypes.FieldDataChangedEvent) => {
2930
if (e.dataField === 'movieId') {
3031
if (e.value) {
3132
const updatedMovie = getMovieById(e.value);

apps/demos/Demos/Scheduler/Templates/Vue/App.vue

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -112,24 +112,26 @@ import DxScheduler, {
112112
DxForm as DxSchedulerForm,
113113
type DxSchedulerTypes,
114114
} from 'devextreme-vue/scheduler';
115-
import DxForm, { DxItem, type DxFormTypes } from 'devextreme-vue/form';
115+
import { DxItem, type DxFormTypes } from 'devextreme-vue/form';
116116
import { type DxSelectBoxTypes } from 'devextreme-vue/select-box';
117-
import type { OptionChangedEvent as PopupOptionChangedEvent } from 'devextreme/ui/popup';
118-
import query from 'devextreme/data/query';
117+
import { type DxPopupTypes } from 'devextreme-vue/popup';
118+
import { query } from 'devextreme-vue/common/data';
119119
import type { MovieResource } from './data.ts';
120120
import AppointmentTemplate from './AppointmentTemplate.vue';
121121
import AppointmentTooltipTemplate from './AppointmentTooltipTemplate.vue';
122122
import MovieInfoContainer from './MovieInfoContainer.vue';
123123
import { data, moviesData, theatreData } from './data.ts';
124124
125+
type dxForm = NonNullable<DxFormTypes.InitializedEvent['component']>;
126+
125127
const views = ['day', 'week', 'timelineDay'];
126128
const groups = ['theatreId'];
127129
const scheduler = ref<DxScheduler['instance']>();
128130
const currentDate = new Date(2025, 3, 27);
129131
const dataSource = data;
130132
131133
const currentMovie = ref<MovieResource | null | undefined>(null);
132-
const formInstance = ref<DxForm['instance'] | null>(null);
134+
const formInstance = ref<dxForm | null>(null);
133135
134136
const getMovieById = (resourceId: number): MovieResource | undefined =>
135137
query(moviesData)
@@ -143,7 +145,7 @@ const getEditorStylingMode = (): 'filled' | 'outlined' => {
143145
144146
const priceDisplayExpr = (value: number): string => `$${value}`;
145147
146-
const updateEndDate = (form: NonNullable<DxForm['instance']>, movie: MovieResource): void => {
148+
const updateEndDate = (form: dxForm, movie: MovieResource): void => {
147149
const formData = form.option('formData');
148150
const { startDate } = formData;
149151
if (startDate && movie?.duration) {
@@ -170,7 +172,7 @@ const onPriceEditorContentReady = (e: DxSelectBoxTypes.ContentReadyEvent): void
170172
e.component.option('stylingMode', getEditorStylingMode());
171173
};
172174
173-
const onPopupOptionChanged = (e: PopupOptionChangedEvent): void => {
175+
const onPopupOptionChanged = (e: DxPopupTypes.OptionChangedEvent): void => {
174176
if (e.fullName === 'toolbarItems' && e.value) {
175177
e.value.forEach((item: any, index: number) => {
176178
if (item.shortcut === 'done' || item.shortcut === 'cancel') {

apps/react-storybook/stories/scheduler/SchedulerFormCustomization.stories.tsx

Lines changed: 106 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { Meta, StoryObj } from "@storybook/react";
2-
import React from "react";
2+
import React, { useRef } from "react";
33
import dxScheduler from "devextreme/ui/scheduler";
44
import type { Properties } from "devextreme/ui/scheduler";
55
import { wrapDxWithReact } from "../utils";
@@ -8,6 +8,9 @@ import "./form-customization.css";
88

99
const Scheduler = wrapDxWithReact<Properties>(dxScheduler);
1010

11+
import ReactScheduler from 'devextreme-react/scheduler';
12+
import dxForm from "devextreme/ui/form";
13+
1114
const iconsShowModeArgType = {
1215
"editing.form.iconsShowMode": {
1316
control: "radio",
@@ -332,21 +335,117 @@ export const RTL: Story = {
332335
export const LegacyPopup: Story = {
333336
args: {
334337
...baseConfig,
335-
"editing.form.iconsShowMode": "none",
338+
"editing.form.iconsShowMode": "both",
336339
} as Properties,
337340
argTypes: iconsShowModeArgType,
338341
render: (args) => {
342+
let form: InstanceType<typeof dxForm> | null = null;
343+
344+
const schedulerRef = useRef(null);
345+
339346
return (
340-
<Scheduler
347+
// @ts-ignore
348+
<ReactScheduler
349+
ref={schedulerRef}
341350
{...baseConfig}
351+
onAppointmentUpdating={(e) => {
352+
delete e.newData.repeat;
353+
}}
354+
onAppointmentAdding={(e) => {
355+
delete e.appointmentData.repeat;
356+
}}
342357
editing={{
358+
popup: {
359+
maxWidth: 800,
360+
toolbarItems: [
361+
{
362+
toolbar: 'top',
363+
location: 'before',
364+
text: "Edit Appointment",
365+
cssClass: 'dx-toolbar-label',
366+
},
367+
{
368+
toolbar: 'top',
369+
location: 'after',
370+
options: {
371+
stylingMode: 'contained',
372+
type: 'default',
373+
onClick: () => {
374+
// @ts-ignore
375+
schedulerRef.current?.instance()?.hideAppointmentPopup(true);
376+
},
377+
text: 'Save',
378+
},
379+
shortcut: 'done',
380+
},
381+
{
382+
toolbar: 'top',
383+
location: 'after',
384+
shortcut: 'cancel',
385+
},
386+
],
387+
},
343388
form: {
389+
onInitialized: function (e) {
390+
e.component?.on('fieldDataChanged', (e) => {
391+
if (e.dataField === 'recurrenceRule') {
392+
form?.option('formData.repeat', !!e.value)
393+
}
394+
});
395+
},
396+
onContentReady: function (e) {
397+
form = e.component;
398+
},
399+
iconsShowMode: args["editing.form.iconsShowMode"],
344400
items: [
345-
"mainGroup",
346-
{name: 'recurenceGroup', visible: true}
401+
{
402+
name: "mainGroup",
403+
cssClass: "",
404+
items: [
405+
"subjectGroup",
406+
"dateGroup",
407+
{
408+
name: "repeatGroup",
409+
items: [
410+
"repeatIcon",
411+
{
412+
name: "customRepeatEditor",
413+
editorType: "dxSwitch",
414+
dataField: "repeat",
415+
editorOptions: {
416+
onValueChanged: (e) => {
417+
if (e.value) {
418+
const recurrenceRule = form?.option('formData')?.recurrenceRule;
419+
420+
form?.option("colCount", 2);
421+
form?.option('formData.recurrenceRule', recurrenceRule || "FREQ=DAILY");
422+
form?.itemOption("recurrenceGroup", "visible", true);
423+
} else {
424+
form?.option("colCount", 1);
425+
form?.option('formData.recurrenceRule', "");
426+
form?.itemOption("recurrenceGroup", "visible", false);
427+
}
428+
},
429+
},
430+
},
431+
],
432+
},
433+
"resourcesGroup",
434+
"descriptionGroup",
435+
],
436+
},
437+
{
438+
name: "recurrenceGroup",
439+
itemType: "group",
440+
cssClass: "",
441+
visible: false,
442+
items: [
443+
"recurrenceRuleGroup",
444+
"recurrenceEndGroup",
445+
],
446+
},
347447
],
348-
iconsShowMode: args["editing.form.iconsShowMode"]
349-
}
448+
},
350449
} as Properties['editing']}
351450
/>
352451
);

0 commit comments

Comments
 (0)