Skip to content

Commit

Permalink
release of v10.58 (#4333)
Browse files Browse the repository at this point in the history
  • Loading branch information
langz authored Nov 29, 2024
2 parents c56de0c + 93b00bf commit 27f7d0f
Show file tree
Hide file tree
Showing 107 changed files with 2,526 additions and 793 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
} from '@dnb/eufemia/src/extensions/forms'
import { Flex } from '@dnb/eufemia/src'

export const TestdataSchema: JSONSchema = {
export const TestDataSchema: JSONSchema = {
type: 'object',
properties: {
requiredString: { type: 'string' },
Expand Down Expand Up @@ -37,7 +37,7 @@ export const TestdataSchema: JSONSchema = {
required: ['requiredString'],
}

export interface Testdata {
export type TestData = {
requiredString: string
string?: string
number?: number
Expand All @@ -53,7 +53,7 @@ export interface Testdata {
}>
}

export const testdata: Testdata = {
export const testData: TestData = {
requiredString: 'This is a text',
string: 'String value',
number: 123,
Expand Down Expand Up @@ -81,12 +81,12 @@ export const Default = () => {
scope={{
DataContext,
Value,
testdata,
TestdataSchema,
testData,
TestDataSchema,
}}
>
<DataContext.Provider
defaultData={testdata}
defaultData={testData}
onChange={(data) => console.log('onChange', data)}
onPathChange={(path, value) =>
console.log('onPathChange', path, value)
Expand Down Expand Up @@ -177,13 +177,13 @@ export const ValidationWithJsonSchema = () => {
scope={{
DataContext,
Value,
testdata,
TestdataSchema,
testData,
TestDataSchema,
}}
>
<DataContext.Provider
data={testdata}
schema={TestdataSchema}
data={testData}
schema={TestDataSchema}
onChange={(data) => console.log('onChange', data)}
onPathChange={(path, value) =>
console.log('onPathChange', path, value)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import ComponentBox from '../../../../../../shared/tags/ComponentBox'
import { Flex, P } from '@dnb/eufemia/src'
import { Form, Field } from '@dnb/eufemia/src/extensions/forms'
import {
Form,
Field,
Wizard,
Value,
} from '@dnb/eufemia/src/extensions/forms'

export const BasicUsage = () => {
return (
Expand All @@ -19,3 +24,30 @@ export const BasicUsage = () => {
</ComponentBox>
)
}

export const UsageInWizard = () => {
return (
<ComponentBox data-visual-test="forms-card-in-wizard">
<Form.Handler>
<Wizard.Container>
<Wizard.Step>
<Form.Card>
<Form.Section>
<Form.Section.ViewContainer
title="In a Wizard"
variant="basic"
>
<Value.String defaultValue="Something" />
</Form.Section.ViewContainer>
<Form.Section.EditContainer variant="basic">
<Field.String defaultValue="Something" />
</Form.Section.EditContainer>
</Form.Section>
</Form.Card>
</Wizard.Step>
</Wizard.Container>
<Form.SubmitButton text="Happy coding!" />
</Form.Handler>
</ComponentBox>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,7 @@ import * as Examples from './Examples'
## Demos

<Examples.BasicUsage />

<VisibleWhenVisualTest>
<Examples.UsageInWizard />
</VisibleWhenVisualTest>
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: 'Handler'
description: '`Form.Handler` provides both the DataContext.Provider and a HTML form element.'
description: 'The `Form.Handler` is the root component of your form. It provides a HTML form element and handles the form data.'
showTabs: true
tabs:
- title: Info
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,28 +7,126 @@ import AsyncChangeExample from './parts/async-change-example.mdx'

## Description

The `Form.Handler` component provides a HTML form element.
The `Form.Handler` is the root component of your form. It provides a HTML form element and handles the form data.

```tsx
import { Form } from '@dnb/eufemia/extensions/forms'

const existingData = { firstName: 'Nora' }

function MyForm() {
return (
<Form.Handler
defaultData={existingData}
onSubmit={...}
>
Your Form
</Form.Handler>
)
}
```

### TypeScript support

You can define the TypeScript type structure for your data like so:

```tsx
import { Form } from '@dnb/eufemia/extensions/forms'

type MyDataContext = {
firstName?: string
}

// Method #1 – without initial data
function MyForm() {
return (
<Form.Handler<MyDataContext>
onSubmit={(data) => {
// "firstName" is of type string
console.log(data.firstName)
}}
>
...
</Form.Handler>
)
}

// Method #2 – with data (initial values)
const existingData: MyDataContext = {
firstName: 'Nora',
}
function MyForm() {
return (
<Form.Handler
defaultData={existingData}
onSubmit={(data) => {
// "firstName" is of type string
console.log(data.firstName)
}}
>
...
</Form.Handler>
)
}

// Method #3 – type definition on the event parameter
const submitHandler = (data: MyDataContext) => {
// "firstName" is of type string
console.log(data.firstName)
}
function MyForm() {
return <Form.Handler onSubmit={submitHandler}>...</Form.Handler>
}

// Method #4 – type definition for the submit handler
import type { OnSubmit } from '@dnb/eufemia/extensions/forms'
const submitHandler: OnSubmit<MyDataContext> = (data) => {
// "firstName" is of type string
console.log(data.firstName)
}
function MyForm() {
return <Form.Handler onSubmit={submitHandler}>...</Form.Handler>
}
```

To disable types you can:

```tsx
<Form.Handler<any>>...</Form.Handler>
```

## Decoupling the form element

For more flexibility, you can decouple the form element from the form context by using the `decoupleForm` property. It is recommended to use the `Form.Element` to wrap your rest of your form:

```jsx
import { Form } from '@dnb/eufemia/extensions/forms'

render(
<Form.Handler
data={existingData}
onChange={...}
onSubmit={...}
>
Your Form
</Form.Handler>,
)
function MyApp() {
return (
<Form.Handler decoupleForm>
<AppRelatedThings>
<Form.Element>
<Form.MainHeading>Heading</Form.MainHeading>
<Form.Card>
<Field.Email />
</Form.Card>
<Form.SubmitButton />
</Form.Element>
</AppRelatedThings>
</Form.Handler>
)
}
```

The form data can be handled outside of the form. This is useful if you want to use the form data in other components:
## Data handling

You can access, mutate and filter data inside of the form context by using the `Form.useData` hook:

```jsx
import { Form } from '@dnb/eufemia/extensions/forms'

function MyForm() {
function MyComponent() {
const {
getValue,
update,
Expand All @@ -37,9 +135,18 @@ function MyForm() {
data,
filterData,
reduceToVisibleFields,
} = Form.useData('unique')
} = Form.useData()

return <Form.Handler id="unique">...</Form.Handler>
return <>...</>
}

function MyApp() {
return (
<>
<Form.Handler>...</Form.Handler>
<MyComponent />
</>
)
}
```

Expand All @@ -51,53 +158,33 @@ function MyForm() {
- `filterData` will filter the data based on your own logic.
- `reduceToVisibleFields` will reduce the given data set to only contain the visible fields (mounted fields).

More examples can be found in the [useData](/uilib/extensions/forms/Form/useData/) hook docs.

### TypeScript support
### Using a form ID

You can define the TypeScript type structure for your data like so:
The form data can be handled outside of the form. This is useful if you want to use the form data in other components:

```tsx
```jsx
import { Form } from '@dnb/eufemia/extensions/forms'

type MyDataSet = {
firstName?: string
}
const myFormId = 'unique-id' // or a function, object or React Context reference

const data: MyDataSet = {
firstName: 'Nora',
function MyComponent() {
const { data } = Form.useData(myFormId)

return <>...</>
}

// Method #1
function MyForm() {
function MyApp() {
return (
<Form.Handler
data={data}
onSubmit={(data) => {
console.log(data.firstName)
}}
/>
<>
<Form.Handler id={myFormId}>...</Form.Handler>
<MyComponent />
</>
)
}

// Method #2
const submitHandler = (data: MyDataSet) => {
console.log(data.firstName)
}
function MyForm() {
return <Form.Handler data={data} onSubmit={submitHandler} />
}

// Method #3
import type { OnSubmit } from '@dnb/eufemia/extensions/forms'
const submitHandler: OnSubmit<MyDataSet> = (data) => {
console.log(data.firstName)
}
function MyForm() {
return <Form.Handler data={data} onSubmit={submitHandler} />
}
```

More examples can be found in the [useData](/uilib/extensions/forms/Form/useData/) hook docs.

## Async `onChange` and `onSubmit` event handlers

**NB:** When using an async `onChange` event handler, the `data` parameter will only include validated data. This lets you utilize the `data` parameter directly in your request, without having to further process or transform it.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ In all async operations, you can simply return an error object to display it in
```tsx
import { Form } from '@dnb/eufemia/extensions/forms'

const myFormId = 'unique-id' // or a function, object or React Context reference

// Async function
const onSubmit = async (data) => {
try {
Expand All @@ -12,7 +14,7 @@ const onSubmit = async (data) => {
})
const data = await response.json()

Form.setData('unique-id', data) // Whatever you want to do with the data
Form.setData(myFormId, data) // Whatever you want to do with the data
} catch (error) {
return error // Will display the error message in the form
}
Expand All @@ -32,7 +34,7 @@ const onSubmit = async (data) => {

function Component() {
return (
<Form.Handler id="unique-id" onSubmit={onSubmit}>
<Form.Handler id={myFormId} onSubmit={onSubmit}>
...
</Form.Handler>
)
Expand Down
Loading

0 comments on commit 27f7d0f

Please sign in to comment.