npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

synergy-form-generator

v1.2.2

Published

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![npm version](https://badge.fury.io/js/synergy-form-generator.svg)](https://badge.fury.io/js/synergy-form-generator)

Downloads

1,363

Readme

Synergy Form Generator

License: MIT npm version

Synergy Form Generator is a dynamic and highly customizable form-building library designed for React. It allows you to generate forms from a JSON schema with support for custom components, dynamic rules, and complex field dependencies.

Key Features

  • JSON Schema-Based Forms: Easily generate entire forms based on a provided JSON schema.
  • Customizable Components: Use the FormGenerator for automatic form generation, or build your form manually by extracting fields and using the FieldComponent. You can also pass custom components as props.
  • Global Component Replacement: Replace default input components like TextInput globally with replaceComponent or setComponents. This ensures that custom inputs are used consistently across the form and application.
  • Dynamic Field Dependencies: Handle complex field interdependencies, such as dynamic rule activation, validation, and field value comparisons.
  • Dynamic Value Comparisons: Compare values dynamically between fields. For example, the minimum value of one field can depend on the value of another.
  • Real-Time Field Updates: Update fields in real-time based on changes in other fields using the fieldsToUpdateOnChange property.

Installation

Install the package via npm:

npm install synergy-form-generator

Or via Yarn

yarn add synergy-form-generator

Usage

Example using FormGenerator

import {
	FormGenerator,
	fieldTypeConstants,
	createForm,
} from "synergy-form-generator";

const schema = [
	{
		type: fieldTypeConstants.text,
		label: "Name",
		name: "name",
		rules: { required: true },
	},
	{
		type: fieldTypeConstants.number,
		label: "Price",
		name: "price",
		rules: {
			required: true,
			min: 10,
		},
	},
];

const handleSubmit = (formData: any) => {
	console.log("Form submitted with:", formData);
};

const form = createForm({ fieldProps: schema, onSubmit: handleSubmit });

function App() {
	return (
		<div>
			<h1>Create a Product</h1>
			<FormGenerator form={form} />
		</div>
	);
}

export default App;

Example using FieldComponent and FormComponent

import {
	fieldTypeConstants,
	createForm,
	FormComponent,
	FieldComponent,
	TFormField,
} from "synergy-form-generator";

const schema = [
	{
		type: fieldTypeConstants.text,
		label: "Name",
		name: "name",
		rules: { required: true },
	},
	{
		type: fieldTypeConstants.number,
		label: "Price",
		name: "price",
		rules: {
			required: true,
			min: 10,
		},
	},
];

const handleSubmit = (formData: any) => {
	console.log("Form submitted with:", formData);
};

const form = createForm({ fieldProps: schema, onSubmit: handleSubmit });

const { fields } = form;
const { name, price } = fields;

const BaseInput = ({ field }: { field: TFormField }) => {
	const { label, error, value, onChange, type, name } = field;
	return (
		<>
			<label>{label}</label>
			<span>{error}</span>
			<input name={name} value={value} onChange={onChange} type={type} />
		</>
	);
};

function App() {
	return (
		<div>
			<h1>Create a Product</h1>
			<FormComponent form={form}>
				<FieldComponent
					field={name}
					component={() => <BaseInput field={name} />}
				/>
				<FieldComponent
					field={price}
					component={() => <BaseInput field={price} />}
				/>
				<input type="submit" />
			</FormComponent>
		</div>
	);
}

export default App;

Replacing default component using ReplaceComponent

import {
	fieldTypeConstants,
	createForm,
	replaceComponent,
	TFieldComponentProps,
	FormGenerator,
} from "synergy-form-generator";

const schema = [
	{
		type: fieldTypeConstants.text,
		label: "Name",
		name: "name",
		rules: {
			required: true,
		},
	},
	{
		type: fieldTypeConstants.number,
		label: "Price",
		name: "price",
		rules: {
			required: true,
			min: 10,
		},
	},
];

const handleSubmit = (formData: any) => {
	console.log("Form submitted with:", formData);
};

const form = createForm({ fieldProps: schema, onSubmit: handleSubmit });

const BaseInput = (props: TFieldComponentProps) => {
	const { label, error, value, onChange, type } = props;
	return (
		<>
			I am now used as a default text Component!
			<label>{label}</label>
			<span>{error}</span>
			<input value={value} onChange={onChange} type={type} />
		</>
	);
};

replaceComponent(fieldTypeConstants.text, BaseInput);

function App() {
	return (
		<div>
			<h1>Create a Product</h1>
			<FormGenerator form={form} />
		</div>
	);
}

export default App;

Dynamic validation example

import {
	fieldTypeConstants,
	createForm,
	FormGenerator,
} from "synergy-form-generator";

const schema = [
	{
		type: fieldTypeConstants.text,
		label: "Min Price",
		name: "minPrice",
	},
	{
		type: fieldTypeConstants.number,
		label: "Price",
		name: "price",
		rules: {
			min: {
				isActive: ({ minPrice }) => minPrice > 0,
				value: ({ minPrice }) => minPrice,
			},
		},
		dependencies: ["minPrice"],
	},
	{
		type: fieldTypeConstants.text,
		label: "Max Price",
		name: "maxPrice",
		rules: {
			required: ({ minPrice }) => minPrice > 0,
		},
		dependencies: ["minPrice"],
	},
];

const handleSubmit = (formData: any) => {
	console.log("Form submitted with:", formData);
};

const form = createForm({ fieldProps: schema, onSubmit: handleSubmit });

function App() {
	return (
		<div>
			<h1>Create a Product</h1>
			<FormGenerator form={form} />
		</div>
	);
}

export default App;

Custom validation and custom dynamic validation example

import {
	fieldTypeConstants,
	createForm,
	FormGenerator,
} from "synergy-form-generator";

const schema = [
	{
		type: fieldTypeConstants.text,
		label: "Username",
		name: "username",
		customRules: [
			{
				name: "usernameCheck",
				validator: ({ value }) => {
					if (value.includes("123")) {
						return {
							isValid: false,
							error: "Username cannot contain value 123",
						};
					}
					return {
						isValid: true,
						error: undefined,
					};
				},
				isActive: true,
			},
		],
	},
	{
		type: fieldTypeConstants.password,
		label: "Password",
		name: "password",
		customRules: [
			{
				name: "passwordCheck",
				validator: ({ value, form }) => {
					const { fields } = form;
					const { username } = fields;

					if (value.includes(username.value)) {
						return {
							isValid: false,
							error: "Password cannot contain Username",
						};
					}
					return {
						isValid: true,
						error: undefined,
					};
				},
				isActive: ({ username }) => !!username,
			},
		],
		dependencies: ["username"],
	},
];

const handleSubmit = (formData: any) => {
	console.log("Form submitted with:", formData);
};

const form = createForm({ fieldProps: schema, onSubmit: handleSubmit });

function App() {
	return (
		<div>
			<FormGenerator form={form} />
		</div>
	);
}

export default App;

Props

FieldProps

FieldProps is a configuration object used to define the behavior and characteristics of form fields. This configuration is used by the FormField to render fields dynamically. Below are the props available in FieldProps:

| Prop | Type | Description | | ------------------------ | --------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | name | string | The unique identifier for the field. | | label | string | The label displayed for the field. | | type | TFieldComponentType | The type of the field component (e.g., text, dropdown). | | customComponent | FunctionComponent | A custom React component that can be used to render the field instead of the default component. | | rules | TSynergyRules | Validation rules defined for the field, such as required or minLength. | | customRules | TCustomRules | An array of custom validation rules specific to the field. Each rule includes a name and validation function. | | placeholder | string | Placeholder text to display in the field. | | dependencies | Array<string> | Defines field dependencies. This array contains other field names that the current field depends on for validation or behavior. | | getItems | TGeTSelectableItemsFunc | A function to fetch selectable items for fields such as dropdowns or radio buttons. It can be synchronous or asynchronous. | | hideField | boolean \| (values: any) => boolean | Determines if the field should be hidden. Can be a boolean or a function that returns a boolean based on form values. | | items | Array<TSelectableItem> | A static array of items used for dropdown or radio fields. | | fieldClassName | string | CSS class applied to the field container. | | labelClassName | string | CSS class applied to the field label. | | errorClassName | string | CSS class applied to the error message container. | | inputClassName | string | CSS class applied to the field input element. | | filter | any | An object containing filter criteria used for fetching selectable items. | | updateFilter | (filter: any) => any | A function to update the filter object when fetching items dynamically. | | watch | (field: TFormField) => void | A callback that is triggered when the field's value changes. | | fieldsToUpdateOnChange | Array<{name: string, updateFunc: (values: any) => any}> | An array of field objects that are updated when the value of this field changes. updateFunc receives current form values and returns the updated value for the target field. |

FormField

FormField represents an individual field in the form. It is created based on the configuration from FieldProps. Here are the properties available in FormField:

| Prop | Type | Description | | --------------------------- | --------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | | name | string | The unique identifier for the field. | | label | string | The label displayed for the field. | | type | TFieldComponentType | The type of the field component (e.g., text, dropdown). | | value | any | The current value of the field. | | onChange | ChangeEventHandler<HTMLInputElement> | Event handler that triggers when the field's value changes. | | component | TSynergyFieldComponent | The custom component used to render the field. | | id | string | The unique identifier for the field. | | isValid | boolean | Whether the field is valid based on validation rules. | | error | string \| undefined | The error message for the field, if validation fails. | | dependencies | Array<string> | An array of field names this field depends on for validation or behavior. | | rules | Array<TRule> | An array of validation rules applied to the field. | | form | TForm | The form that this field belongs to. | | errors | Array<{ error: string; rule: string }> | An array of error objects, each containing an error message and the rule that caused the error. | | hasChanged | () => boolean | Returns true if the field's value has changed from its initial state. | | clear | () => void | Clears the field's value. | | reset | () => void | Resets the field's value to its initial state. | | disable | () => void | Disables the field, preventing user interaction. | | enable | () => void | Enables the field for user interaction. | | disabled | boolean | Whether the field is currently disabled. | | placeholder | string \| undefined | The placeholder text displayed in the field. | | setRules | () => void | Sets the validation rules for the field. | | appendDependencyCallbacks | () => void | Appends callbacks for field dependencies to handle conditional logic. | | fieldsToUpdateOnChange | Array<{name: string, updateFunc: (values: any) => any}> | Defines fields to update when this field changes. Each object contains a field name and an updateFunc that returns the new value based on form values. |

Form

Form represents the structure and behavior of a form, providing a dictionary of fields, error handling, and form lifecycle methods. Below are the properties available in Form:

| Prop | Type | Description | | ------------- | -------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | | fields | { [key: string]: TFormField } | A dictionary where each key is the name of a field and the value is a TFormField object that contains the configuration and state of the field. | | errors | Array<{ field: string; errors: Array<{ rule: string; error: string }> }> | An array of error objects for the form. Each object contains a field name and an array of errors related to that field, including the rule and message. | | options | TOptions | A configuration object containing various settings and options for the form. | | onSubmit | Function | The function that will be called when the form is submitted. | | isValid | boolean | A boolean indicating whether the form is valid based on its fields and validation rules. | | values | { [key: string]: any } | A dictionary of the current values of the form fields, indexed by their field names. | | entity | any | The entity associated with the form, which can store context or additional data related to the form. | | addField | (field: TFormField) => void | A method to add a new field to the form. The argument is a TFormField object. | | hasChanged | () => boolean | Checks if any of the form's values have changed from their initial state. Returns true if any value has changed, otherwise false. | | clear | () => void | Clears all values in the form, resetting them to empty or default values. | | reset | () => void | Resets the form values to their initial state (typically the state when the form was first loaded or initialized). | | disable | () => void | Disables all fields in the form, making them unmodifiable. | | enable | () => void | Enables all fields in the form, allowing user interaction and modifications. | | clearErrors | () => void |

Hooks

createField(fieldProps: TFieldProps, form: TForm, addToForm: boolean = true)

Creates a new field based on the provided field properties.

createForm<TEntity>({ EntityClass, fieldProps, onSubmit, options, entity, }: { fieldProps: Array<TFieldProps>; onSubmit: Function; options?: TOptions; entity?: TEntity EntityClass?: new () => TEntity; })

Creates a new form based on the provided form properties.

replaceComponent(type: TFieldComponentType, component: TSynergyFieldComponent)

Replaces the component with the specified type, so that it is automatically used whenever the field with the specified type is created.

replaceRule ({ name, validator, }: { name: TSynergyRule; validator: (values: any) => { isValid: boolean; error: string | undefined }; })

Replaces the rule with the specified name, so that it is automatically used whenever the rule with the specified type is called.

setComponents(components: { [key: string]: TSynergyFieldComponent })

Performs the same function as replaceComponent, but for multiple components at once.

setRules(rules: Array<{ name: TSynergyRule; validator: (values: any) => { isValid: boolean; error: string | undefined; }; }>)

Performs the same function as replaceRule, but for multiple rules at once.