Skip to content

Commit 68ecf17

Browse files
Stepper Form Demo: update way to set Stepper readonly (#30176)
1 parent 3f14b7f commit 68ecf17

File tree

10 files changed

+93
-81
lines changed

10 files changed

+93
-81
lines changed

apps/demos/Demos/Stepper/FormIntegration/Angular/app/app.component.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,7 @@
3333
display: flex;
3434
gap: 8px;
3535
}
36+
37+
::ng-deep .readonly {
38+
pointer-events: none;
39+
}

apps/demos/Demos/Stepper/FormIntegration/Angular/app/app.component.html

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
<dx-stepper
2+
[focusStateEnabled]="!isStepperReadonly"
3+
[class.readonly]="isStepperReadonly"
24
[(selectedIndex)]="selectedIndex"
35
(onSelectionChanging)="onSelectionChanging($event)"
46
>
@@ -61,7 +63,7 @@
6163
<div class="current-step">
6264
<span *ngIf="!isConfirmed">
6365
Step <span class="selected-index">{{ selectedIndex + 1 }}</span> of
64-
<span class="step-count">{{ steps.length }}</span>
66+
{{ steps.length }}
6567
</span>
6668
</div>
6769
<div class="nav-buttons">

apps/demos/Demos/Stepper/FormIntegration/Angular/app/app.component.ts

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,16 @@ export class AppComponent {
4545

4646
isConfirmed: boolean;
4747

48+
isStepperReadonly: boolean;
49+
4850
validationGroups = ['dates', 'guests', 'roomAndMealPlan'];
4951

5052
constructor(private readonly appService: AppService) {
5153
this.steps = this.appService.getInitialSteps();
5254
this.formData = this.appService.getInitialFormData();
5355
this.selectedIndex = 0;
5456
this.isConfirmed = false;
55-
56-
this.getNextButtonText = this.getNextButtonText.bind(this);
57+
this.isStepperReadonly = false;
5758
}
5859

5960
getValidationResult(index: number){
@@ -69,12 +70,6 @@ export class AppComponent {
6970
}
7071

7172
onSelectionChanging(e: SelectionChangingEvent) {
72-
if (this.isConfirmed) {
73-
e.cancel = true;
74-
75-
return;
76-
}
77-
7873
const { component, addedItems, removedItems } = e;
7974
const { items = [] } = component.option();
8075

@@ -122,11 +117,13 @@ export class AppComponent {
122117
this.formData = this.appService.getInitialFormData();
123118
validationEngine.resetGroup(this.validationGroups[0]);
124119
validationEngine.resetGroup(this.validationGroups[1]);
120+
this.isStepperReadonly = false;
125121
}
126122

127123
confirm(){
128124
this.isConfirmed = true;
129125
this.setStepValidationResult(this.selectedIndex, true);
126+
this.isStepperReadonly = true;
130127
}
131128

132129
onNextButtonClick() {

apps/demos/Demos/Stepper/FormIntegration/React/App.tsx

Lines changed: 32 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,28 @@ export default function App () {
2222
const [steps, setSteps] = useState<IItemProps[]>(initialSteps);
2323
const [formData, setFormData] = useState<BookingFormData>(getInitialFormData);
2424
const [isConfirmed, setIsConfirmed] = useState(false);
25+
const [isStepperReadonly, setIsStepperReadonly] = useState(false);
26+
27+
const getValidationResult = useCallback((index: number) => {
28+
if (index >= validationGroups.length) {
29+
return true;
30+
}
31+
32+
return validationEngine.validateGroup(validationGroups[index]).isValid;
33+
}, []);
34+
35+
const setStepValidationResult = useCallback((index: number, isValid: boolean | undefined) => {
36+
setSteps((prev) => prev.map((step, i) => {
37+
if (i === index) {
38+
return {
39+
...step,
40+
isValid,
41+
}
42+
}
43+
44+
return step;
45+
}));
46+
}, []);
2547

2648
const onPrevButtonClick = useCallback(() => {
2749
setSelectedIndex((prev) => prev - 1);
@@ -35,18 +57,20 @@ export default function App () {
3557
if (isValid){
3658
setSelectedIndex(selectedIndex + 1);
3759
}
38-
}, [selectedIndex]);
60+
}, [getValidationResult, selectedIndex, setStepValidationResult]);
3961

4062
const onConfirm = useCallback(() => {
4163
setIsConfirmed(true);
4264
setStepValidationResult(initialSteps.length - 1, true);
43-
}, []);
65+
setIsStepperReadonly(true);
66+
}, [setStepValidationResult]);
4467

4568
const onReset = useCallback(() => {
4669
setIsConfirmed(false);
4770
setSteps(initialSteps);
4871
setSelectedIndex(0);
4972
setFormData(getInitialFormData);
73+
setIsStepperReadonly(false);
5074
}, []);
5175

5276
const onNextButtonClick = useCallback(() => {
@@ -57,7 +81,7 @@ export default function App () {
5781
} else {
5882
onConfirm();
5983
}
60-
}, [selectedIndex, isConfirmed, onConfirm, onReset]);
84+
}, [selectedIndex, isConfirmed, onConfirm, onReset, moveNext]);
6185

6286
const nextButtonText = useMemo(() => {
6387
if (selectedIndex < steps.length - 1) {
@@ -69,36 +93,9 @@ export default function App () {
6993
}
7094

7195
return 'Confirm';
72-
}, [selectedIndex, isConfirmed]);
73-
74-
const getValidationResult = useCallback((index: number) => {
75-
if (index >= validationGroups.length) {
76-
return true;
77-
}
78-
79-
return validationEngine.validateGroup(validationGroups[index]).isValid;
80-
}, []);
81-
82-
const setStepValidationResult = useCallback((index: number, isValid: boolean | undefined) => {
83-
setSteps((prev) => prev.map((step, i) => {
84-
if (i === index) {
85-
return {
86-
...step,
87-
isValid,
88-
}
89-
}
90-
91-
return step;
92-
}));
93-
}, []);
96+
}, [selectedIndex, isConfirmed, steps.length]);
9497

9598
const onSelectionChanging = useCallback((args: SelectionChangingEvent) => {
96-
if (isConfirmed) {
97-
args.cancel = true;
98-
99-
return;
100-
}
101-
10299
const { component, addedItems, removedItems } = args;
103100
const { items = [] } = component.option();
104101

@@ -115,7 +112,7 @@ export default function App () {
115112
args.cancel = true;
116113
}
117114
}
118-
}, [setStepValidationResult, isConfirmed]);
115+
}, [setStepValidationResult, getValidationResult]);
119116

120117
const onSelectionChanged = useCallback(({ component }: SelectionChangedEvent) => {
121118
setSelectedIndex(component.option('selectedIndex') ?? 0);
@@ -144,6 +141,8 @@ export default function App () {
144141
return (
145142
<>
146143
<Stepper
144+
className={ isStepperReadonly ? 'readonly' : ''}
145+
focusStateEnabled={!isStepperReadonly}
147146
selectedIndex={selectedIndex}
148147
onSelectionChanged={onSelectionChanged}
149148
onSelectionChanging={onSelectionChanging}
@@ -172,7 +171,7 @@ export default function App () {
172171
<>
173172
Step <span className="selected-index">{selectedIndex + 1}</span>
174173
{' of '}
175-
<span className="step-count">{steps.length}</span>
174+
{steps.length}
176175
</>
177176
)}
178177
</div>

apps/demos/Demos/Stepper/FormIntegration/React/styles.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,7 @@
6868
display: flex;
6969
gap: 8px;
7070
}
71+
72+
.readonly {
73+
pointer-events: none;
74+
}

apps/demos/Demos/Stepper/FormIntegration/ReactJs/App.js

Lines changed: 29 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,25 @@ export default function App() {
1616
const [steps, setSteps] = useState(initialSteps);
1717
const [formData, setFormData] = useState(getInitialFormData);
1818
const [isConfirmed, setIsConfirmed] = useState(false);
19+
const [isStepperReadonly, setIsStepperReadonly] = useState(false);
20+
const getValidationResult = useCallback((index) => {
21+
if (index >= validationGroups.length) {
22+
return true;
23+
}
24+
return validationEngine.validateGroup(validationGroups[index]).isValid;
25+
}, []);
26+
const setStepValidationResult = useCallback((index, isValid) => {
27+
setSteps((prev) =>
28+
prev.map((step, i) => {
29+
if (i === index) {
30+
return {
31+
...step,
32+
isValid,
33+
};
34+
}
35+
return step;
36+
}));
37+
}, []);
1938
const onPrevButtonClick = useCallback(() => {
2039
setSelectedIndex((prev) => prev - 1);
2140
}, []);
@@ -25,16 +44,18 @@ export default function App() {
2544
if (isValid) {
2645
setSelectedIndex(selectedIndex + 1);
2746
}
28-
}, [selectedIndex]);
47+
}, [getValidationResult, selectedIndex, setStepValidationResult]);
2948
const onConfirm = useCallback(() => {
3049
setIsConfirmed(true);
3150
setStepValidationResult(initialSteps.length - 1, true);
32-
}, []);
51+
setIsStepperReadonly(true);
52+
}, [setStepValidationResult]);
3353
const onReset = useCallback(() => {
3454
setIsConfirmed(false);
3555
setSteps(initialSteps);
3656
setSelectedIndex(0);
3757
setFormData(getInitialFormData);
58+
setIsStepperReadonly(false);
3859
}, []);
3960
const onNextButtonClick = useCallback(() => {
4061
if (selectedIndex < initialSteps.length - 1) {
@@ -44,7 +65,7 @@ export default function App() {
4465
} else {
4566
onConfirm();
4667
}
47-
}, [selectedIndex, isConfirmed, onConfirm, onReset]);
68+
}, [selectedIndex, isConfirmed, onConfirm, onReset, moveNext]);
4869
const nextButtonText = useMemo(() => {
4970
if (selectedIndex < steps.length - 1) {
5071
return 'Next';
@@ -53,31 +74,9 @@ export default function App() {
5374
return 'Reset';
5475
}
5576
return 'Confirm';
56-
}, [selectedIndex, isConfirmed]);
57-
const getValidationResult = useCallback((index) => {
58-
if (index >= validationGroups.length) {
59-
return true;
60-
}
61-
return validationEngine.validateGroup(validationGroups[index]).isValid;
62-
}, []);
63-
const setStepValidationResult = useCallback((index, isValid) => {
64-
setSteps((prev) =>
65-
prev.map((step, i) => {
66-
if (i === index) {
67-
return {
68-
...step,
69-
isValid,
70-
};
71-
}
72-
return step;
73-
}));
74-
}, []);
77+
}, [selectedIndex, isConfirmed, steps.length]);
7578
const onSelectionChanging = useCallback(
7679
(args) => {
77-
if (isConfirmed) {
78-
args.cancel = true;
79-
return;
80-
}
8180
const { component, addedItems, removedItems } = args;
8281
const { items = [] } = component.option();
8382
const addedIndex = items.findIndex((item) => item === addedItems[0]);
@@ -91,7 +90,7 @@ export default function App() {
9190
}
9291
}
9392
},
94-
[setStepValidationResult, isConfirmed],
93+
[setStepValidationResult, getValidationResult],
9594
);
9695
const onSelectionChanged = useCallback(({ component }) => {
9796
setSelectedIndex(component.option('selectedIndex') ?? 0);
@@ -124,6 +123,8 @@ export default function App() {
124123
return (
125124
<React.Fragment>
126125
<Stepper
126+
className={isStepperReadonly ? 'readonly' : ''}
127+
focusStateEnabled={!isStepperReadonly}
127128
selectedIndex={selectedIndex}
128129
onSelectionChanged={onSelectionChanged}
129130
onSelectionChanging={onSelectionChanging}
@@ -157,7 +158,7 @@ export default function App() {
157158
<React.Fragment>
158159
Step <span className="selected-index">{selectedIndex + 1}</span>
159160
{' of '}
160-
<span className="step-count">{steps.length}</span>
161+
{steps.length}
161162
</React.Fragment>
162163
)}
163164
</div>

apps/demos/Demos/Stepper/FormIntegration/ReactJs/styles.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,7 @@
6868
display: flex;
6969
gap: 8px;
7070
}
71+
72+
.readonly {
73+
pointer-events: none;
74+
}

apps/demos/Demos/Stepper/FormIntegration/Vue/App.vue

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<template>
22
<DxStepper
3+
:focus-state-enabled="!isStepperReadonly"
4+
:class="{ readonly: isStepperReadonly }"
35
v-model:selected-index="selectedIndex"
46
@selection-changing="onSelectionChanging"
57
>
@@ -61,9 +63,7 @@
6163
<div class="nav-panel">
6264
<div class="current-step">
6365
<span v-if="!isConfirmed">
64-
Step <span class="selected-index">{{ selectedIndex + 1 }}</span> of <span class="step-count">{{
65-
steps.length
66-
}}</span>
66+
Step <span class="selected-index">{{ selectedIndex + 1 }}</span> of {{ steps.length }}
6767
</span>
6868
</div>
6969
<div class="nav-buttons">
@@ -105,6 +105,7 @@ import type { BookingFormData } from './types';
105105
106106
const selectedIndex = ref(0);
107107
const isConfirmed = ref(false);
108+
const isStepperReadonly = ref(false);
108109
const steps = ref<IItemProps[]>(getInitialSteps());
109110
const formData = ref<BookingFormData>(getInitialFormData());
110111
@@ -131,12 +132,6 @@ const setStepValidationResult = (index: number, isValid: boolean | undefined) =>
131132
};
132133
133134
function onSelectionChanging(e: SelectionChangingEvent) {
134-
if (isConfirmed.value) {
135-
e.cancel = true;
136-
137-
return;
138-
}
139-
140135
const { component, addedItems, removedItems } = e;
141136
const { items = [] } = component.option();
142137
@@ -176,11 +171,13 @@ const reset = () => {
176171
formData.value = getInitialFormData();
177172
validationEngine.resetGroup(validationGroups[0]);
178173
validationEngine.resetGroup(validationGroups[1]);
174+
isStepperReadonly.value = false;
179175
};
180176
181177
const confirm = () => {
182178
isConfirmed.value = true;
183179
setStepValidationResult(selectedIndex.value, true);
180+
isStepperReadonly.value = true;
184181
};
185182
186183
function onNextButtonClick() {
@@ -265,4 +262,8 @@ function onNextButtonClick() {
265262
display: flex;
266263
gap: 8px;
267264
}
265+
266+
.readonly {
267+
pointer-events: none;
268+
}
268269
</style>

apps/demos/Demos/Stepper/FormIntegration/jQuery/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
<div class="content">
1919
<div id="stepContent"></div>
2020
<div class="nav-panel">
21-
<div class="current-step"> Step <span class="selected-index">1</span> of 5<span class="step-count"></span> </div>
21+
<div class="current-step"> Step <span class="selected-index">1</span> of 5</div>
2222
<div class="nav-buttons">
2323
<div id="prevButton"></div>
2424
<div id="nextButton"></div>

0 commit comments

Comments
 (0)