ferm

dynamic form generation for the frontend

Usage no npm install needed!

<script type="module">
  import ferm from 'https://cdn.skypack.dev/ferm';
</script>

README

Ferm

Generate forms and form handling logic on the client, including validation.

npm install ferm

Simple example

var fields = ferm.fields;
var validators = ferm.validators;

var registrationForm = ferm.post('/login/', {
    username: fields.string({
        required: 'Username is required',
        validators: validators.lengthRange(3, 25)
    }),
    password: fields.password({
        required: true,
        validators: [validators.minLength(5), 
                    validators.match('password2', 'The passwords do not match')]
    }),
    password2: fields.password({
        required: true,
        validators: [validators.minLength(5), 
                    validators.match('password', 'The passwords do not match')],
        label: 'repeat password:'
    }),
    submit: fields.button({
        type: 'submit',
        text: 'submit',
    }),
});

registrationForm.success(function(data) {
    ajaxPost(registrationForm.url, data);
});

document.body.appendChild(registrationForm.element);

Produces the following HTML:

<form method="POST" action="/login/">
    <div class="form-group">
        <label for="id_username">username:</label>
        <input id="id_username" name="username" type="text">
    </div>
    <div class="form-group">
        <label for="id_password">password:</label>
        <input id="id_password" name="password" type="password">
    </div>
    <div class="form-group">
        <label for="id_password2">repeat password:</label>
        <input id="id_password2" name="password2" type="password">
    </div>
    <button type="submit">submit</button>
</form>

Validation

By default, ferm form elements have their submit event overridden. Validators are run against each field, rendering errors according to a specific format:

<span class="form-error form-error-{{field.name}} form-error-{{field.type}}">
    {{error message}}
</span>

Errors are rendered immediately after fields. Fields can have multiple validators defined. They are called in order of definition. If a validator fails, the remaining validators for the field will not be called.

Validators

Validators must be functions to be called during the validation process. Each function will be called with three parameters: the form, the field, and the input value. To be treated as a failure, the function must return text to be displayed as an error. To pass, it should return either nothing, or a falsy value. Most default validators are functions that return functions.

The following example is the 'match' validator, allowing two fields to be validated against each other.

validators.match = function(name, message) {
    return function(form, field, value) {
        var matcher = form.getField(name);
        if (matcher.value !== value) {
            return (message !== undefined) ? message : field.name + ' does not match ' + matcher.name;
        }
    };
};

Default validators

  • required(message)
  • min(minimum, message)
  • max(maximum, message)
  • range(minimum, maximum, message)
  • minLength(maximum, message)
  • maxLength(minimum, message)
  • lengthRange(minimum, maximum, message)
  • match(name, message)

Submission

Add a function to call after validation sucessfully passes.

form.success(function(data) {
    ajaxPost(form.url, data);
});

Fields

  • string
  • number
  • tel
  • url
  • date
  • email
  • password
  • boolean
  • select

Button is included under the 'ferm.fields' namespace, but does not register as a field for most purposes.

Field options

  • default (set default value)
  • required
  • label
  • widget
  • name (input name attribute)

Widgets

A widget must be a function that accepts a field object and an options object as parameters. The function must set two properties on the field object: field.element and field.html. field.element must be the field input element, and field.html must be the entire html for the field, which usually includes the input and label.

Misc

Form.getField

form.getField(name);

Returns field with specified name.