Skip to content

Commit 35788db

Browse files
authored
docs(Form): add edit & display-only mode example (#4957)
1 parent dfa60e7 commit 35788db

File tree

2 files changed

+226
-0
lines changed

2 files changed

+226
-0
lines changed

packages/main/src/components/Form/Form.mdx

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import * as ComponentStories from './Form.stories';
99

1010
<DocsHeader since="0.7.0" />
1111

12+
**Note:** For more detailed examples of how the form can be used or integrated with other external libraries such as "React Hook Form", you can visit our [knowledge base](https://sap.github.io/ui5-webcomponents-react/?path=/docs/knowledge-base-form-handling--docs).
13+
1214
<br />
1315

1416
## Example
@@ -135,6 +137,122 @@ const FormComponent = (props) => {
135137

136138
</details>
137139

140+
## Display-Only and Edit mode
141+
142+
<Canvas of={ComponentStories.DisplayEditMode} sourceState="none" />
143+
144+
### Code
145+
146+
<details>
147+
148+
<summary>Show Code</summary>
149+
150+
```jsx
151+
const StandardField = ({ editMode, value, inputType = InputType.None, onInput, ...rest }) => {
152+
if (editMode) {
153+
return <Input value={value} style={{ width: '100%' }} type={inputType} onInput={onInput} {...rest} />;
154+
}
155+
if (inputType === InputType.URL || inputType === InputType.Email) {
156+
return (
157+
<Link href={inputType === InputType.Email ? `mailto:${value}` : value} target="_blank" {...rest}>
158+
{value}
159+
</Link>
160+
);
161+
}
162+
return <Text {...rest}>{value}</Text>;
163+
};
164+
165+
const reducer = (state, { field, value }) => {
166+
return { ...state, [field]: value };
167+
};
168+
169+
const FormComponent = (props) => {
170+
const [editMode, toggleEditMode] = useReducer((prev) => !prev, false, undefined);
171+
const [formState, dispatch] = useReducer(
172+
reducer,
173+
{
174+
name: 'Red Point Stores',
175+
street: 'Main St 1618',
176+
zip: 31415,
177+
city: 'Maintown',
178+
country: 'Germany',
179+
web: 'https://www.sap.com',
180+
181+
twitter: '@sap',
182+
phone: '+49 1234 56789'
183+
},
184+
undefined
185+
);
186+
const { zip, city, name, street, country, web, mail, twitter, phone } = formState;
187+
188+
const handleInput = (e) => {
189+
dispatch({ field: Object.keys(e.target.dataset)[0], value: e.target.value });
190+
};
191+
192+
return (
193+
<>
194+
<Button onClick={toggleEditMode}>Toggle {editMode ? 'Display-Only Mode' : 'Edit Mode'}</Button>
195+
<Form
196+
{...props}
197+
onSubmit={(e) => {
198+
e.preventDefault();
199+
}}
200+
>
201+
<FormGroup titleText="Address">
202+
<FormItem label="Name">
203+
<StandardField editMode={editMode} value={name} onInput={handleInput} data-name />
204+
</FormItem>
205+
<FormItem label="Street">
206+
<StandardField editMode={editMode} value={street} onInput={handleInput} data-street />
207+
</FormItem>
208+
<FormItem label="ZIP Code / City">
209+
{editMode ? (
210+
<>
211+
<Input value={zip} type={InputType.Number} style={{ width: '30%' }} onInput={handleInput} data-zip />
212+
<Input value={city} style={{ width: '70%' }} onInput={handleInput} data-city />
213+
</>
214+
) : (
215+
<Text>{`${zip} ${city}`}</Text>
216+
)}
217+
</FormItem>
218+
<FormItem label="Country">
219+
<StandardField editMode={editMode} value={country} onInput={handleInput} data-country />
220+
</FormItem>
221+
<FormItem label="Web">
222+
<StandardField editMode={editMode} value={web} inputType={InputType.URL} onInput={handleInput} data-web />
223+
</FormItem>
224+
</FormGroup>
225+
<FormGroup titleText="Contact">
226+
<FormItem label="Email">
227+
<StandardField
228+
editMode={editMode}
229+
value={mail}
230+
inputType={InputType.Email}
231+
onInput={handleInput}
232+
data-email
233+
/>
234+
</FormItem>
235+
<FormItem label="Twitter">
236+
<StandardField editMode={editMode} value={twitter} onInput={handleInput} data-twitter />
237+
</FormItem>
238+
<FormItem label="Phone">
239+
<StandardField
240+
editMode={editMode}
241+
value={phone}
242+
inputType={InputType.Tel}
243+
onInput={handleInput}
244+
data-phone
245+
/>
246+
</FormItem>
247+
</FormGroup>
248+
</Form>
249+
</>
250+
);
251+
};
252+
```
253+
254+
</details>
255+
138256
<Markdown>{SubcomponentsSection}</Markdown>
139257

140258
## Form Group

packages/main/src/components/Form/Form.stories.tsx

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import type { Meta, StoryObj } from '@storybook/react';
2+
import { useReducer } from 'react';
23
import {
4+
Button,
35
CheckBox,
46
FormBackgroundDesign,
57
FormGroup,
@@ -222,3 +224,109 @@ export const FormWithCustomComponents: Story = {
222224
);
223225
}
224226
};
227+
228+
const StandardField = ({ editMode, value, inputType = InputType.None, onInput, ...rest }) => {
229+
if (editMode) {
230+
return <Input value={value} style={{ width: '100%' }} type={inputType} onInput={onInput} {...rest} />;
231+
}
232+
if (inputType === InputType.URL || inputType === InputType.Email) {
233+
return (
234+
<Link href={inputType === InputType.Email ? `mailto:${value}` : value} target="_blank" {...rest}>
235+
{value}
236+
</Link>
237+
);
238+
}
239+
return <Text {...rest}>{value}</Text>;
240+
};
241+
242+
const reducer = (state, { field, value }) => {
243+
return { ...state, [field]: value };
244+
};
245+
246+
export const DisplayEditMode: Story = {
247+
name: 'Display & Edit mode',
248+
args: { titleText: 'Supplier' },
249+
render: (args) => {
250+
const [editMode, toggleEditMode] = useReducer((prev) => !prev, false, undefined);
251+
const [formState, dispatch] = useReducer(
252+
reducer,
253+
{
254+
name: 'Red Point Stores',
255+
street: 'Main St 1618',
256+
zip: 31415,
257+
city: 'Maintown',
258+
country: 'Germany',
259+
web: 'https://www.sap.com',
260+
261+
twitter: '@sap',
262+
phone: '+49 1234 56789'
263+
},
264+
undefined
265+
);
266+
const { zip, city, name, street, country, web, mail, twitter, phone } = formState;
267+
268+
const handleInput = (e) => {
269+
dispatch({ field: Object.keys(e.target.dataset)[0], value: e.target.value });
270+
};
271+
272+
return (
273+
<>
274+
<Button onClick={toggleEditMode}>Toggle {editMode ? 'Display-Only Mode' : 'Edit Mode'}</Button>
275+
<Form
276+
{...args}
277+
onSubmit={(e) => {
278+
e.preventDefault();
279+
}}
280+
>
281+
<FormGroup titleText="Address">
282+
<FormItem label="Name">
283+
<StandardField editMode={editMode} value={name} onInput={handleInput} data-name />
284+
</FormItem>
285+
<FormItem label="Street">
286+
<StandardField editMode={editMode} value={street} onInput={handleInput} data-street />
287+
</FormItem>
288+
<FormItem label="ZIP Code / City">
289+
{editMode ? (
290+
<>
291+
<Input value={zip} type={InputType.Number} style={{ width: '30%' }} onInput={handleInput} data-zip />
292+
<Input value={city} style={{ width: '70%' }} onInput={handleInput} data-city />
293+
</>
294+
) : (
295+
<Text>{`${zip} ${city}`}</Text>
296+
)}
297+
</FormItem>
298+
<FormItem label="Country">
299+
<StandardField editMode={editMode} value={country} onInput={handleInput} data-country />
300+
</FormItem>
301+
<FormItem label="Web">
302+
<StandardField editMode={editMode} value={web} inputType={InputType.URL} onInput={handleInput} data-web />
303+
</FormItem>
304+
</FormGroup>
305+
<FormGroup titleText="Contact">
306+
<FormItem label="Email">
307+
<StandardField
308+
editMode={editMode}
309+
value={mail}
310+
inputType={InputType.Email}
311+
onInput={handleInput}
312+
data-email
313+
/>
314+
</FormItem>
315+
<FormItem label="Twitter">
316+
<StandardField editMode={editMode} value={twitter} onInput={handleInput} data-twitter />
317+
</FormItem>
318+
<FormItem label="Phone">
319+
<StandardField
320+
editMode={editMode}
321+
value={phone}
322+
inputType={InputType.Tel}
323+
onInput={handleInput}
324+
data-phone
325+
/>
326+
</FormItem>
327+
</FormGroup>
328+
</Form>
329+
</>
330+
);
331+
}
332+
};

0 commit comments

Comments
 (0)