Skip to content

Commit

Permalink
feat(forms): add autocomplete (autofill) support (#2811)
Browse files Browse the repository at this point in the history
This allows us to use:

```tsx
<Form.Hander>
  <Field.String autoComplete="first-name" path="/your-pointer" />
  <Field.String autoComplete="last-name" path="/your-pointer" />
</Form.Hander>
```
or

```tsx
<Form.Hander autoComplete={true}>
  <Field.String path="/firstName" />
  <Field.String path="/lastName" />
</Form.Hander>
```

---------

Co-authored-by: Anders <[email protected]>
  • Loading branch information
tujoworker and langz authored Oct 31, 2023
1 parent 72de227 commit 342556c
Show file tree
Hide file tree
Showing 32 changed files with 376 additions and 102 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,10 @@ When building your application forms, preferably use the following layout compon

To build an entire form, there are surrounding components such as [Form.Handler](/uilib/extensions/forms/extended-features/Form/Handler) and [StepsLayout](/uilib/extensions/forms/extended-features/StepsLayout) that make data flow and layout easier and save you a lot of extra code, without compromising flexibility.

#### Related topics

- [Best Practices on Forms](/uilib/extensions/forms/best-practices-on-forms/).

### Value components

Beside the interactive [Field](/uilib/extensions/forms/create-component/Field/) components, there are also the static [Value](/uilib/extensions/forms/create-component/Value/) components. Use these to show summaries or read-only parts of your application with benefits such as linking to source data and standardized formatting based on the type of data to be displayed.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,7 @@ showTabs: true
`Field.Number` is the base component for receiving user input where the target data is of type `number`.

There is a corresponding [Value.Number](/uilib/extensions/forms/create-component/Value/Number) component.

## Autocomplete and autofill

Check out the [Field.String](/uilib/extensions/forms/base-fields/String/#autocomplete-and-autofill) docs about autocomplete.
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,5 @@ import DataValueReadwriteProperties from '../../data-value-readwrite-properties.
| `multipleOf` | `number` | _(optional)_ Validation that requires the number to be a multiple of given value. |
| `width` | `string` or `false` | _(optional)_ `false` for no width (use browser default), `small`, `medium` or `large` for predefined standard widths, `stretch` for fill available width. |
| `help` | `object` | _(optional)_ Provide a help button. Object consisting of `title` and `contents` |
| `autoComplete` | `on` or `string` | _(optional)_ For HTML `autocomplete` [attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete). |
| [Space](/uilib/layout/space/properties) | Various | _(optional)_ Spacing properties like `top` or `bottom` are supported. |
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,27 @@ showTabs: true
`Field.String` is the base component for receiving user input where the target data is of type `string`.

There is a corresponding [Value.String](/uilib/extensions/forms/create-component/Value/String) component.

## Autocomplete and autofill

The string component does support HTML `autocomplete` [attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete).

1. You may either set the property directly on each field:

```tsx
<Form.Handler>
<Field.String autoComplete="first-name" path="/your-pointer" />
<Field.String autoComplete="last-name" path="/your-pointer" />
</Form.Handler>
```

2. Or use the "less-code" approach, by just giving the data pointer `path` a meaningful name:

```tsx
<Form.Handler autoComplete={true}>
<Field.String path="/firstName" />
<Field.String path="/lastName" />
</Form.Handler>
```

The `path` property will be used to set the `name` attribute.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import DataValueReadwriteProperties from '../../data-value-readwrite-properties.
| `innerRef` | `React.ref` | _(optional)_ by providing a React.ref we can get the internally used input element (DOM). E.g. `innerRef={myRef}` by using `React.createRef()` or `React.useRef()`. |
| `clear` | `boolean` | _(optional)_ True to have a clickable clear-icon for removing the active value |
| `autoresize` | `boolean` | _(optional)_ For `multiline`, set true to expand when writing longer texts. |
| `autoComplete` | `on` or `string` | _(optional)_ For HTML `autocomplete` [attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete). |
| `autoresizeMaxRows` | `boolean` | _(optional)_ For `multiline`, set how many rows of text can be shown at max. |
| `characterCounter` | `boolean` | _(optional)_ True to show a character counter. |
| `minLength` | `boolean` | _(optional)_ Validation for minimum length of the text (number of characters) |
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
breadcrumb:
- text: Forms
href: /uilib/extensions/forms/
- text: Best Practices on Forms
href: /uilib/extensions/forms/best-practice-on-forms/
---

# Best Practices on Forms

- Ensure you have a `form` element. It will add support for additional keyboard and auto-complete features. Use the [Form.Handler](/uilib/extensions/forms/extended-features/Form/Handler/) that uses the [Form.Element](/uilib/extensions/forms/extended-features/Form/Element/) under the hood.
- Ensure your form HTML elements have a semantic and unique `name`. By using the `path` property (e.g. `path="/firstName"`), it will set an unique `name` attribute to the rendered HTML element.
- Ensure you have a submit button. Use the [Form.SubmitButton](/uilib/extensions/forms/extended-features/Form/SubmitButton/) for that.
- Ensure to let browser autofill personal data if applicable, based on HTML [autocomplete attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete). By using the `path` property with semantic names (e.g. `path="/firstName"`), browser will be able to provide a correct autofill integration.
- In some cases, it is appreciated to temporary store user entered input data. Use the `sessionStorageId` feature provided by [Form.Handler](/uilib/extensions/forms/extended-features/Form/Handler/) for that.

```jsx
<Form.Handler autoComplete={true}>
<Field.String path="/firstName" />
<Field.Email path="/email" />
<Form.SubmitButton>Submit</Form.SubmitButton>
</Form.Handler>
```
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,19 @@

| Property | Type | Description |
| ---------------------- | --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `className` | `string` | _(optional)_ Outer DOM element class name |
| `value` | {<code>{props.type}</code>} | _(optional)_ Source data value for the input |
| `layout` | `string` | _(optional)_ Layout for the label and input. Can be `horizontal` or `vertical` |
| `label` | `string` | _(optional)_ Field label to show above / before the input feature |
| `labelDescription` | `string` | _(optional)_ A more discreet text displayed beside the label (i.e for "(optional)") |
| `labelSecondary` | `string` | _(optional)_ Secondary information displayed at the end of the label line (i.e character counter) |
| `placeholder` | `string` | _(optional)_ Text showing in place of the value if no value is given |
| `path` | `string` | _(optional)_ JSON Pointer for where the data for this input is located in the source dataset (when using DataContext) |
| `info` | `Error` or `string` | _(optional)_ Info message shown below / after the input |
| `warning` | `Error` or `string` | _(optional)_ Warning message shown below / after the input |
| `error` | `Error` | _(optional)_ Error message shown below / after the input |
| `className` | `string` | _(optional)_ Outer DOM element class name. |
| `value` | {<code>{props.type}</code>} | _(optional)_ Source data value for the input. |
| `id` | `string` | _(optional)_ Outer DOM element id attribute. |
| `name` | `string` | _(optional)_ Outer DOM element name attribute. |
| `layout` | `string` | _(optional)_ Layout for the label and input. Can be `horizontal` or `vertical`. |
| `label` | `string` | _(optional)_ Field label to show above / before the input feature. |
| `labelDescription` | `string` | _(optional)_ A more discreet text displayed beside the label (i.e for "(optional)"). |
| `labelSecondary` | `string` | _(optional)_ Secondary information displayed at the end of the label line (i.e character counter). |
| `placeholder` | `string` | _(optional)_ Text showing in place of the value if no value is given. |
| `path` | `string` | _(optional)_ JSON Pointer for where the data for this input is located in the source dataset (when using Form.Handler or DataContext). The `path` will also be sett as the `name` attribute for the [string](/uilib/extensions/forms/base-fields/String/)-field. |
| `info` | `Error` or `string` | _(optional)_ Info message shown below / after the input. |
| `warning` | `Error` or `string` | _(optional)_ Warning message shown below / after the input. |
| `error` | `Error` | _(optional)_ Error message shown below / after the input. |
| `disabled` | `boolean` | _(optional)_ Set `true` to show the field but without the possibility of changing the value. |
| `emptyValue` | `any` | _(optional)_ The value to use (in `onChange` events etc) when emptying the field. Makes it possible for instance to provide `undefined` instead of an empty string when clearing the content of a text input. |
| `required` | `boolean` | _(optional)_ When set `true`, the input will give an error if the value cannot be empty. |
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import ComponentBox from '../../../../../../../shared/tags/ComponentBox'
import { Form, Field } from '@dnb/eufemia/src/extensions/forms'
import { Card } from '@dnb/eufemia/src'
import { Form, Field, FieldBlock } from '@dnb/eufemia/src/extensions/forms'
import { Card, Flex, P } from '@dnb/eufemia/src'

export const Default = () => {
return (
Expand Down Expand Up @@ -38,3 +38,56 @@ export const SessionStorage = () => {
</ComponentBox>
)
}

export const Autofill = () => {
return (
<ComponentBox>
<Form.Handler
onSubmit={(event) => console.log('onSubmit', event)}
autoComplete
>
<Form.MainHeading>Delivery address</Form.MainHeading>

<Card stack>
<Form.SubHeading>Your name</Form.SubHeading>

<Field.String label="First name" path="/firstName" required />
<Field.String label="Last name" path="/lastName" required />
</Card>

<Card stack>
<Form.SubHeading>Your address</Form.SubHeading>

<FieldBlock label="Address">
<Flex.Horizontal>
<Field.String
label="Street"
width="medium"
path="/streetName"
required
/>
<Field.Number
label="Nr."
width="small"
path="/streetNr"
required
/>
</Flex.Horizontal>
</FieldBlock>

<Field.PostalCodeAndCity
postalCode={{ required: true, path: '/postalCode' }}
city={{ required: true, path: '/city' }}
/>
</Card>

<Card spacing="medium">
<P>More information about this form.</P>
<Form.ButtonRow>
<Form.SubmitButton />
</Form.ButtonRow>
</Card>
</Form.Handler>
</ComponentBox>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@ import * as Examples from './Examples'

### With session storage

<em>
Changes you make to the fields are saved to session storage and loaded
when the browser reload (as long as it is the same session)
</em>
Changes you make to the fields are temporarily saved and loaded
when the browser reloads. The data is stored until the session storage is invalidated.

<Examples.SessionStorage />

### Autocomplete (autofill) user data

<Examples.Autofill />
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,19 @@ render(
)
```

## Autocomplete and autofill

You can set `autoComplete` on the `Form.Handler` – each [Field.String](/uilib/extensions/forms/base-fields/String/)-field will then get `autoComplete="on"`:

```tsx
<Form.Handler autoComplete={true}>
<Field.String path="/firstName" />
<Field.String path="/lastName" />
</Form.Handler>
```

The `path` property will be used to set the `name` attribute, which lets browser know which autocomplete value should be proposed to the user.

## Temporary storage

The `sessionStorageId` feature uses the browsers session-storage (temporary storage mechanism) to store data entered by the user.
Expand Down
Loading

0 comments on commit 342556c

Please sign in to comment.