Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: added support for array fields with different uiControl type #480

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
## 4.61.1 ( Jan 13th, 2024)

### Fixed

- Issue where fieldExists was not added to formApi

## 4.61.0 ( Dec 12th, 2024)

### Added

- React 19 as supported version

## 4.60.5 ( Nov 21st, 2024)

### Fixed
Expand Down
32 changes: 16 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ const ExampleForm = () => (
- Scope: ability to scope ( group ) fields
- Schema: ability to render forms based on pure JSON schema
- Dynaic: ability to hide and show fields ( render and unrender ) and either cleanup or maintain state of unmounted fields
- Debugging: ability to easily debug users state as well as internals of the library
- Nesting: ability to have highly nested value strucutre `state.values.friends[1].brother.parents.cars[0].model`
- Debugging: ability to easily debug user's state as well as internals of the library
- Nesting: ability to have highly nested value structure `state.values.friends[1].brother.parents.cars[0].model`

## Creating Your Own Fields

Expand Down Expand Up @@ -194,8 +194,8 @@ Informed took the following into consideration when being built:
- **Performance:** `informed` was designed to be able to handle very complex forms at scale
- Ability to render a form with thousands of fields on screen
- Ability to bulk update thousands of fields at a time
- **Readability** `informed` was designed to be able to write complex forms with very litle **intuitive** code
- Reads naturlly like with pure JSX:
- **Readability** `informed` was designed to be able to write complex forms with very little **intuitive** code
- Reads naturally like with pure JSX:

```jsx
<Form onSubmit={onSubmit}>
Expand Down Expand Up @@ -230,7 +230,7 @@ Informed took the following into consideration when being built:
- Scope: ability to scope ( group ) fields
- Schema: ability to render forms based on pure JSON schema
- Dynaic: ability to hide and show fields ( render and unrender ) and either cleanup or maintain state of unmounted fields
- Debugging: ability to easily debug users state as well as internals of the library
- Debugging: ability to easily debug user's state as well as internals of the library
- Nesting: ability to have highly nested value strucutre `state.values.friends[1].brother.parents.cars[0].model`

---
Expand Down Expand Up @@ -273,9 +273,9 @@ project_root
│ ├── hooks # helper hooks for docs
│ ├── Nav # side nav of the docs
│ ├── Pages # main level pages of the app
│ │ ├──ApiReference # Self explanitory :)
│ │ ├──ApiReference # Self explanatory :)
│ │ ├──Examples # Examples of all sorts of usecases
│ │ ├──GettingStarted # Also Self explanitory :)
│ │ ├──GettingStarted # Also Self explanatory :)
│ │ └──Playground.jsx # Uses Sandpack to allow users to test any of the examples
│ │
│ ├── SideBySide.jsx # helper component for showing code example and output side by side
Expand All @@ -288,7 +288,7 @@ project_root
├── hooks # tests for informed hooks
├── ObjectMap.test # tests for the internal data structure
├── Schema.test # tests for usage of JSON schema rendered forms
└── utils.test # tests for interanal library utilites
└── utils.test # tests for internal library utilities
```

---
Expand All @@ -301,7 +301,7 @@ FormController is the brains of informed, it holds the `state` object and is res

- Managing the form state
- Tracking all form fields via registration/deregistration
- Managing events. FormController impliments its own event hanlder ( a few lines of code at bottom of file )
- Managing events. FormController implements its own event hand;er ( a few lines of code at bottom of file )

#### `ObjectMap`

Expand All @@ -317,11 +317,11 @@ ObjectMap.set(state.values, 'friends[0].brothers.age', 30);

#### `useField`

useField is the first class citizen of informed, its responsible for registering a field by name to the FormController.
useField is the first class citizen of informed, it's responsible for registering a field by name to the FormController.

#### Context

Thouh there is not explicitly a component called `Context` here the concept is KEY to understanding informed. Context alows us to register fields in a highly nested structure and allows us to do wild things such as scoping.
Though there is not explicitly a component called `Context` here the concept is KEY to understanding informed. Context alows us to register fields in a highly nested structure and allows us to do wild things such as scoping.

---

Expand Down Expand Up @@ -376,13 +376,13 @@ Below depicts the core to how this library works. Form controller is the master

### Types ( Type Script )

I know, I know the types kinda suck. I personally dont use typescript so I have had to rely on other TS wizard devs to help maintain the types. When trying to type very complex objects such as `FormState` especially parts like `FormState.values` which can literally be an object that conatins anything there are lots of opinions on how to properly type it. Im activly seeking help here.
I know, I know the types kinda suck. I personally don't use typescript so I have had to rely on other TS wizard devs to help maintain the types. When trying to type very complex objects such as `FormState` especially parts like `FormState.values` which can literally be an object that contains anything there are lots of opinions on how to properly type it. I'm actively seeking help here.

---

### Documentation

As stated earlier, docs now live in the vitedocs directory. Its called `vitedocs` because I migrated them from storybook to now use a custom singe page react app built with `vite`... pernounced "veet" by the way :)
As stated earlier, docs now live in the vitedocs directory. Its called `vitedocs` because I migrated them from storybook to now use a custom singe page react app built with `vite`... pronounced "veet" by the way :)

#### What to expect

Expand Down Expand Up @@ -410,8 +410,8 @@ import exampleCode from './Example.jsx?raw';

### TODO/Improvements

- re-write the internal implimentation of how schemas are rendered, that code is not my favorite
- re-write the internal implementation of how schemas are rendered, that code is not my favorite
- re-write the way multistep forms work. Currently they step through each step when navigating to a step only initializing the values for that step when its rendered
- allow an evaluate function to be passed into a form field ( i.e useField ). Currently this is not possible because evaluate re computes props to be passed to the component using useField but it would be nice to not have to call the `useConditional` hook.
- allow an evaluate function to be passed into a form field ( i.e useField ). Currently this is not possible because evaluate recomputes props to be passed to the component using useField but it would be nice to not have to call the `useConditional` hook.
- move the rest of the schema docs over to the new docs ( I simply have not had the time to do this )
- Types ... I know, I know the types kinda suck. I personally dont use typescript so I have had to rely on other TS wizard devs to help maintain the types.
- Types ... I know, I know the types kinda suck. I personally don't use typescript so I have had to rely on other TS wizard devs to help maintain the types.
10 changes: 6 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "informed",
"version": "4.60.5",
"version": "4.61.1",
"description": "A lightweight framework and utility for building powerful forms in React applications",
"type": "module",
"main": "dist/cjs/index.js",
Expand Down Expand Up @@ -138,10 +138,10 @@
"yup": "^0.28.1"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
},
"optionalDependencies": {
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
},
"nyc": {
"instrument": false,
Expand Down
8 changes: 7 additions & 1 deletion src/FormController.js
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ export class FormController {
this.enableForm = this.enableForm.bind(this);
this.getMemory = this.getMemory.bind(this);
this.restore = this.restore.bind(this);
this.fieldExists = this.fieldExists.bind(this);
}

getOptions() {
Expand All @@ -214,6 +215,10 @@ export class FormController {
return ObjectMap.get(this.state.maskedValues, name);
}

fieldExists(name) {
return !!this.fieldsMap.get(name);
}

setMaskedValue(name, value) {
return ObjectMap.set(this.state.maskedValues, name, value);
}
Expand Down Expand Up @@ -772,7 +777,8 @@ export class FormController {
disable: this.disableForm,
enable: this.enableForm,
restore: this.restore,
getMemory: this.getMemory
getMemory: this.getMemory,
fieldExists: this.fieldExists
};
}

Expand Down
4 changes: 2 additions & 2 deletions src/components/FormField.js
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ const FormField = ({ name, schema, ...rest }) => {
}

// User created custom array field
if (Component && componentType === 'array' && items && type === 'array') {
if (Component && items && type === 'array') {
return (
<Component
name={name}
Expand Down Expand Up @@ -276,7 +276,7 @@ const FormField = ({ name, schema, ...rest }) => {
}

// Note we DONT pass in scoped name here because useField is already scoped
return <Component name={name} {...props} />;
return <Component name={name} {...props} items={items} />;
};

export { FormField };