Awesome
hyperapp-forms
Hyperapp form state management library
- Simple
- Small in size (3kb minified)
Heavily inspired by redux-form
Installation
npm i -S hyperapp-forms
Usage
Import
Add the imported actions object contents to the main actions object.
import forms from 'hyperapp-forms';
..
const actions = {
..
...forms,
};
..
app(state,actions,view,document.body);
Field components
Wrap your input components with the Field
decorator.
Textbox.js
import { h } from 'hyperapp';
import {Field} from "hyperapp-forms";
const Textbox = ({ input, type, name, title, disabled }) => {
const showError = (input.touched || input.submitted) && !!input.error;
return (
<label>
{title}
<input type={type}
name={name}
value={input.value}
disabled={disabled}
onchange={input.onchange}
onfocus={input.onfocus}
/>
{showError && <sup>{input.error}</sup>}
</label>
);
};
export default Field(Textbox);
The attributes the Field
decorator adds to the component are:
Attribute | Type | Description |
---|---|---|
form | string | The form's name |
name | string | The field's name |
validate | function(form, name, values) : Object | A validate function to run after change |
Actions
changeAndValidate({ form, name, value, validate })
Changes a value for a certain field, also runs the validate
function and updates the sync errors accordingly.
validate
is a callback with the following structure validate(form, name, values)
(see explanation above).
touch({ form, name })
Sets the field as been touched.
startSubmit({ form })
Sets the form's status to be submitting
stopSubmit({ form, errors })
Sets the form's status to be not submitting, and apply server errors by matching field names.
Selectors
Selector | Description |
---|---|
getFormValues(state, form) | Get an object with the form values |
isSubmitting(state, form) | Is the form submitting |
isValid(state, form) | Is the form valid (are there any errors) |
wasSubmitted(state, form) | Was the form submitted at least once (useful for showing errors) |
getFieldValue(state, form, field) | Get a certain field value |
getFieldError(state, form, field) | Get a certain field error |
isFieldTouched(state, form, field) | Was field touched (useful for showing errors) |
Submission and error handling
handleSubmit(state, actions, form, callback)
Use handleSubmit
in the form's onsubmit (or any button's callback, see example below),
Supply a callback function which will return a promise, which at first will start the form's submission automatically.
And once resolved or rejected will stop the form's submission.
The callback function needs to be in the following structure:
callback(values, actions) : Promise
The resolve or reject argument should be
Usage example
Checkout a working example: hyperapp-less-boilerplate
const signIn = (values, actions) => new Promise((resolve, reject) => {
setTimeout(() => {
if (values.username === 'test') {
actions.login.login();
resolve();
}
else {
reject({ username: 'Not "test"!'});
}
}, 2000);
});
const validate = (form, name, values) => {
let errors = null;
const usernameInvalid = !/^t/.test(values.username);
if (usernameInvalid) {
if (!errors) errors = {};
errors.username = 'not starting with t!';
}
const passwordInvalid = !values.password;
if (passwordInvalid) {
if (!errors) errors = {};
errors.password = 'password is required!';
}
return errors; // if everything is valid, returns null
};
export default (state, actions) => {
const submitting = isSubmitting(state, 'login');
return (
<form onsubmit={handleSubmit(state, actions, 'login', signIn)}>
<h2>Login to your account:</h2>
<Textbox type="text" form="login" name="username" title="Username" disabled={submitting} validate={validate}/>
<Textbox type="password" form="login" name="password" title="Password" disabled={submitting} validate={validate}/>
<Checkbox form="login" name="rememberMe" title="Remember me" disabled={submitting}/>
<button disabled={submitting}>Sign In</button>
{submitting && <div data-loader />}
</form>
);
});