Security News
PyPI’s New Archival Feature Closes a Major Security Gap
PyPI now allows maintainers to archive projects, improving security and helping users make informed decisions about their dependencies.
a-plus-forms
Advanced tools
I love making forms. Forms are fantastic usage of my time
-- Nobody ever
Let me introduce you to the A+ forms
, a react forms library that makes forms
creation a civilized and enjoyable process.
There are two principles A+ forms
are build on top:
onSubmit
prop.If you want to more, here is more:
~7.5k
in size and zero depsnpm install a-plus-forms
yarn add a-plus-forms
First thing to understand about A+ forms
is that the inputs in this system
are abstractions. Those inputs convey the structure of the form, and, depending
on a context, they can render different desirable results.
import { Form, EmailInput, PasswordInput } from 'a-plus-forms';
<Form onSubmit={signInAction}>
<EmailInput name="username" label="Username" />
<PasswordInput name="password" label="Password" />
<button>Sign In</button>
</Form>
In this example, the signInAction
will receive an object that looks like this:
{
username: '...',
password: '...'
}
Inputs in A+ forms
are simply standard interfaces, to style them according
to your needs we use the concept of layouts. Which are basically dumb components
that consistently render all inputs in a form. For example:
const MyLayout = ({ label, error, input }) =>
<div className="my-input">
<label>{label}</label>
<div className="input-container">{input}</div>
{error ? <small className="error">{error}</small> : null}
</div>;
In this case, label
is the label one specifies in the input props. error
is
a validation error string, and input
is the actual input field element.
Now that you have a layout, you have options:
// set this layout as a default layout globally
import { config } from 'a-plus-forms';
config.defaultLayout = MyLayout;
// specify the layout as a default via a layout provider
import { LayoutProvider } from 'a-plus-forms';
<App>
<LayoutProvider layout={MyLayout}>
// content....
</LayoutProvider>
</App>
// render a specific form with this layout
<Form onSubmit={handler} layout={MyLayout}>
// all inputs here will use that layout
</Form>
// render an individual input with this layout
<EmailInput name="username" layout={MyLayout} />
You also can render any input without any layout decoration whatsoever, which is useful when you start making compound.
<TextInput name="something" layout={null} />
// will render simply this
<input type="text" name="something" />
import { connect } from 'react-redux';
import { Form, EmailInput, PasswordInput } from 'a-plus-forms';
import { signIn } from './actions';
const dispatchToProps = dispatch => ({
signIn({ username, password }) {
return dispatch(signIn({ username, password }));
}
});
const SignInForm = ({ signIn }) =>
<Form onSubmit={signIn}>
<EmailInput name="username" label="Username" />
<PasswordInput name="password" label="Password" />
<button>Sign In</button>
</Form>;
export default connect(null, dispatchToProps)(SignInForm);
NOTE: if the signIn
action returns a Promise
the form will automatically
mark the form as disabled for the duration of the server request.
A+ forms
have several validation options. A very simple one is to just pass
a function into the schema
prop:
const validate = (data) => {
if (!data.username) return { username: 'is required' };
};
const SignInForm = ({ signIn }) =>
<Form onSubmit={signIn} schema={validate}>
<EmailInput name="username" label="Username" />
<PasswordInput name="password" label="Password" />
</Form>;
Whenever the validation function returns data, the form will automatically pass the errors into the respective fields. All the pristine/dirty states are automatically taken care of.
One also can create custom re-usable validators and pass them around via a
ValidatorProvider
component:
import { ValidatorProvider } from 'a-plus-forms';
class CustomValidator {
errorsFor(data) {
if (!data.username) {
return { username: 'is required' };
}
}
}
<ValidatorProvider validator={CustomValidator}>
<SignInForm signIn={signIn} />
</ValidatorProvider>
Async validators are also supported out of the box:
class CustomValidator {
async errorsFor({ username }) {
const taken = await api.get('/username-check', { username });
if (taken) {
return { username: 'is already taken' };
}
}
}
For a reference implementation of custom validators, please see the JSON Schema validator plugin
Where A+ forms
really shine is the ease of creation of new custom inputs. A
very simple use case would look somewhat like this:
import { field } from 'a-plus-forms';
const MyCustomInput = ({ value, onChange }) =>
<input type="text" value={value} onChange={onChange} />;
export default field(MyCustomInput);
Essentially, the field
decorator is where the magic happens, it takes care of
all the state, errors and layouts management for you. The only think you need
to provide back a controlled input that understands value
and onChange
.
You can also re-use/re-wrap existing inputs to build extra functionality into the fields:
import { field, TextInput } from 'a-plus-forms';
const PhoneNumberInput = props => {
const { onChange, ...rest } = props;
const format = userInput => toPhoneNumber(userInput);
return (
<TextInput
{...rest}
layout={null} // <- render the input only
onChange={value => onChange(format(value))}
/>
);
}
For more examples, please see the collection of the built in inputs
One can easily combine several inputs into one compound input if needed.
import { field, TextInput } from 'a-plus-forms';
const AddressInput = field({ nested: true })(
() => (
<div>
<TextInput name="country" layout={false} />
<TextInput name="state" layout={false} />
<TextInput name="city" layout={false} />
</div>
)
);
const ProfileForm = ({ onSubmit }) =>
<Form onSubmit={onSubmit}>
<AddressInput name="address" />
</Form>;
When the user submits the form, the onSubmit
function will receive a structure
that looks like so:
{
address: {
country: '...',
state: '...',
city: '...'
}
}
All source code in this repository released under the terms of the ISC license.
Copyright (C) 2017 Nikolay Nemshilov
FAQs
A+ forms. Would use again
The npm package a-plus-forms receives a total of 25 weekly downloads. As such, a-plus-forms popularity was classified as not popular.
We found that a-plus-forms demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
PyPI now allows maintainers to archive projects, improving security and helping users make informed decisions about their dependencies.
Research
Security News
Malicious npm package postcss-optimizer delivers BeaverTail malware, targeting developer systems; similarities to past campaigns suggest a North Korean connection.
Security News
CISA's KEV data is now on GitHub, offering easier access, API integration, commit history tracking, and automated updates for security teams and researchers.