cluster0:autoform

v7.1.38Published last year

AutoForm

AutoForm is a Meteor package that adds UI components and helpers to easily create basic forms with automatic insert and update events, and automatic reactive validation. Versions 6+ of this package require that you separately install the simpl-schema NPM package. Prior versions require and automatically install the simple-schema Meteor package. You can optionally use it with the collection2 package, which you have to add to your app yourself.

Test suite Project Status: Active – The project has reached a stable, usable state and is being actively developed. JavaScript Style Guide LGTM Grade GitHub

NOTE: AutoForm 7.0

AutoForm 7.0 is now available and decouples from the default themes. You will have to install themes manually!

Be sure to check out the change log for full details, first. Note that if you use add-on packages that haven't been updated yet, you will not yet be able to update to version 6.

Add-on Package Authors: Please test your package against AutoForm 7.0, and then release a major version update in which you change your api.use to api.use('aldeed:autoform@7.0.0');. We do NOT recommend using something like api.use('aldeed:autoform@6.0.0 || 7.0.0'); to try to support multiple major versions of AutoForm because there is currently a known Meteor issue where trying to support too many dependency paths leads to running out of memory when trying to resolve dependencies.

Table of Contents

Table of Contents generated with DocToc

Installation

In a Meteor app directory, enter:

$ meteor add aldeed:autoform

Also install SimpleSchema NPM package separately (AutoForm 6+):

$ npm i --save simpl-schema

And then also extend SimpleSchema to allow the autoform option in your schemas, if you plan to use it:

import SimpleSchema from 'simpl-schema';
SimpleSchema.extendOptions(['autoform']);

By default there is no theme included, so you will have to install a theme, too. The following themes are available and tested to work with v7:

Please also consider, that twbs:bootstrap is depending on an outdated (and potential insecure!) Bootstrap version. Better: Use the latest Bootstrap 3.x or 4.x from NPM in favour.

Migration from 6.x

If you update to 7.0.0 you will likely encounter errors from your extension packages like

While selecting package versions:
error: Conflict: Constraint aldeed:autoform@6.3.0 is not satisfied by aldeed:autoform 7.0.0.
Constraints on package "aldeed:autoform":
* aldeed:autoform@=7.0.0 <- top level
* aldeed:autoform@6.3.0 <- someone:packagename x.y.z

You can easily circumvent this issue by editing the package entry in .meteor/packages from aldeed:autoform to aldeed:autoform@7.0.0! (note the exclamation mark).

This is because many extensions will not have the 7.0.0 reference in their package.js file, yet. However, this major version is intended to not break compatibility with extensions, that worked with 6.x. If you encounter any runtime issues with extensions, please open an issue.

Import using static imports

If you come from a previous version and want to "keep things as they were" then this is the option you should choose.

AutoForm now comes only with the core functionality added to the initial package code. In order to make the Templates available, too, you only need to put the following line into your top-level client startup code (for example imports/startup/client/autoform.js):

1import 'meteor/aldeed:autoform/static'

That's it. The Templates are now available.

Import using dynamic imports

This package supports dynamic-import, which helps to reduce initial bundle size of the package from ~110 KB to ~60 KB (estimated via bundle-visualizer).

The following example shows how to import the packages dynamically:

1import 'meteor/aldeed:autoform/dynamic'
2
3AutoForm.load()
4  .then(() => {
5    // ... on init success code, for example set a ReactiveVar to true
6  ))
7  .catch(e => {
8    // ... on error code
9  })

You can even combine this with one of the themes (if they support dynamic imports) like in the following example:

1import { AutoFormThemeBootstrap4 } from 'meteor/communitypackages:autoform-bootstrap4/dynamic'
2import 'meteor/aldeed:autoform/dynamic'
3
4async function init () {
5  await AutoForm.load()
6  await AutoFormThemeBootstrap4.load()
7  // theme is imported, you can now make the form available
8  // you could use a reactive var that resolves to true here
9  // or any other mechanism you like to use to reactively activate the form
10  AutoForm.setDefaultTemplate('bootstrap4')
11}
12
13(function () {
14  init()
15    .catch(e => console.error('[autoForm]: init failed - ', e))
16    .then(() => console.info('[autoForm]: initialized'))
17})()

Note, that you can't use the #autoForm or >quickForm Templates before the import has not completed. You can however use a ReactiveVar in your Temlate to "wait" with rendering the form:

1import { ReactiveVar } from 'meteor/reactive-var'
2import { initAutoForm } from 'meteor/aldeed:autoform/dynamic'
3
4const autoFormLoaded = new ReactiveVar()
5
6initAutoForm()
7  .then(() => autoFormLoaded.set(true))
8  .catch(e => {
9    // ... on error code
10  })
11
12// ... other Template code
13
14Template.myCoolForm.helpers({
15  loadComplete() {
16    return autoFormLoaded.get()
17  }
18})

Community Add-On Packages

Submit a pull request to add your package to this list!

Custom Input Types

Dates and times:

Selects:

WYSIWYGs:

Markdowns:

Autocompletes:

Files:

Maps:

Ranges/Sliders:

Payments

Other:

Themes

Admin Panels

Content Management Systems

Components

Other

Demo

Live

Source

Example

Let's say you have the following Mongo.Collection instance, with schema support provided by the collection2 package. (Adding autoform to your app does not add collection2 by default so you need to run meteor add aldeed:collection2@3.0.0 for this example to work.)

1Books = new Mongo.Collection("books");
2Books.attachSchema(new SimpleSchema({
3  title: {
4    type: String,
5    label: "Title",
6    max: 200
7  },
8  author: {
9    type: String,
10    label: "Author"
11  },
12  copies: {
13    type: Number,
14    label: "Number of copies",
15    min: 0
16  },
17  lastCheckedOut: {
18    type: Date,
19    label: "Last date this book was checked out",
20    optional: true
21  },
22  summary: {
23    type: String,
24    label: "Brief summary",
25    optional: true,
26    max: 1000
27  }
28}, { tracker: Tracker }));

Be sure to define proper insert security for untrusted code if you've removed the insecure package. Call allow/deny or use ongoworks:security.

A Basic Insert Form

1<template name="insertBookForm">
2  {{> quickForm collection="Books" id="insertBookForm" type="insert"}}
3</template>

That's it! This gives you:

  • An autogenerated form that uses the appropriate classes, depending on your theme.
  • Appropriate HTML5 fields for all keys in the "Books" collection schema.
  • A submit button that gathers the entered values and inserts them into

the "Books" collection.

  • Form validation based on the schema attached to the "Books" collection. By default the form

is validated when the user submits. If anything is invalid, the form is continually re-validated on keyup (throttled) as the user fixes the issues.

  • Default validation error messages that appear under the fields, and can be

customized and translated.

A Basic Update Form

An update form is similar to an insert form, except you need to provide the document with the original values to be updated:

1<template name="updateBookForm">
2  {{> quickForm collection="Books" doc=this id="updateBookForm" type="update"}}
3</template>

This example uses doc=this, assuming that you use something like iron:router's data function to set the template's data context to the book document. This is a common way to do it, but you could also use a helper function that returns the document.

Be sure to define proper update security for untrusted code if you've removed the insecure package. Call allow/deny or use ongoworks:security.

A Custom Insert Form

If you want to customize autogenerated forms for all forms, you can easily do so by writing your own templates. Refer to the templates section. However, sometimes a certain form has a complex schema or unique UI requirements, in which case you can use autoForm rather than quickForm, allowing you to define fields individually.

Here's an example:

1<template name="insertBookForm">
2  {{#autoForm collection="Books" id="insertBookForm" type="insert"}}
3    <fieldset>
4      <legend>Add a Book</legend>
5      {{> afQuickField name='title'}}
6      {{> afQuickField name='author'}}
7      {{> afQuickField name='summary' rows=6}}
8      {{> afQuickField name='copies'}}
9      {{> afQuickField name='lastCheckedOut'}}
10    </fieldset>
11    <button type="submit" class="btn btn-primary">Insert</button>
12  {{/autoForm}}
13</template>

In this example, we added rows=6 to the "summary" field, which will cause it to be rendered as a textarea instead of a normal text input field.

Another Custom Insert Form

In the previous example of a custom insert form, we saw how afQuickField can be used to render a field with simple customizations. Now let's say we need to fully customize one of the fields. To do this, you can use the following more specific templates and helpers:

  • afFieldIsInvalid
  • afFieldInput
  • afFieldMessage

Here's an example:

1<template name="insertBookForm">
2  {{#autoForm collection="Books" id="insertBookForm" type="insert"}}
3  <fieldset>
4    <legend>Add a Book</legend>
5    {{> afQuickField name='title'}}
6    {{> afQuickField name='author'}}
7    {{> afQuickField name='summary' rows=6}}
8    {{> afQuickField name='copies'}}
9    {{> afQuickField name='lastCheckedOut'}}
10    <div class="form-group{{#if afFieldIsInvalid name='cost'}} has-error{{/if}}">
11      <div class="input-group">
12        <span class="input-group-addon">$</span>
13        {{> afFieldInput name='cost'}}
14        <span class="input-group-addon">/each</span>
15      </div>
16      {{#if afFieldIsInvalid name='cost'}}
17      <span class="help-block">{{afFieldMessage name='cost'}}</span>
18      {{/if}}
19    </div>
20  </fieldset>
21  <button type="submit" class="btn btn-primary">Insert</button>
22  {{/autoForm}}
23</template>

We added a cost field to our form and customized it to display as an input group with add-ons.

Component and Helper Reference

NOTE: The afDeleteButton component that used to be part of autoform is now available as a separate package.

autoForm

Use this component as a block instead of <form> elements to wrap your form and gain all the advantages of the autoform package.

The following attributes are recognized:

  • collection: Required if schema is not set. Set to one of the following:
    • The name of a helper function (no quotation marks) that returns an

instance of Mongo.Collection that has a schema defined. * The name (in quotation marks) of a Mongo.Collection instance that has a schema defined and is in the window namespace.

  • schema: Required if collection is not set. This schema will be used to generate

and validate the form prior to submission, so you can specify this along with a collection if you want to use a schema that is slightly different from the one your collection uses. However, the final object will still have to pass validation against the collection schema. Set to one of the following: * The name of a helper function (no quotation marks) that returns an instance of SimpleSchema. * The name (in quotation marks) of a SimpleSchema instance that is in the window namespace.

  • id: Required. This is used as the id attribute on the rendered form

element, so it must be unique within your entire application. It's required because we use it to set up a form-specific validation context and to preserve input values when a "hot code push" happens.

  • doc: Required for an update form, and must have at least an _id property. Pass the current document

object, retrieved with a call to findOne() for example. For an insert form, you can also use this attribute to pass an object that has default form values set (the same effect as setting a value attribute on each field within the form).

  • validation: Optional. See the "Fine Tuning Validation" section.
  • template: Optional. See the "Templates" section.
  • type: Optional. The form type. Default if not provided is "normal". See Form Types.
  • meteormethod: Optional. When type is "method" or "method-update", indicate the name of the

Meteor method in this attribute.

  • ddp: Optional. When type is "method" or "method-update", provide an alternative DDP Connection that should be used to call the Meteor method in this attribute.
  • resetOnSuccess: Optional. The form is automatically reset

for you after a successful submission action. You can skip this by setting this attribute to false.

  • autosave: Optional. Set to true to enable automatic form submission. Whenever the form change event is emitted, the change will be automatically saved to the database.
  • autosaveOnKeyup: Optional. Set to true to enable automatic form submission for a type="update form on keyup event. Whenever a keyup event is emitted on a form field, the change will be automatically saved to the database (throttled to 500ms). It's best to set trimStrings=false when using this option. If you don't, spaces may be deleted while typing.
  • filter: Optional. Set to false for an insert or update form to skip filtering out unknown properties when cleaning the form document.
  • autoConvert: Optional. Set to false for an insert or update form to skip autoconverting property values when cleaning the form document.
  • removeEmptyStrings: Optional. Set to false for an insert or update form to keep empty string values when cleaning the form document.
  • trimStrings: Optional. Set to false for an insert or update form to keep leading and trailing spaces for string values when cleaning the form document.
  • setArrayItems: Optional. Set to true for an update form that is updating specific array items. Note that there is a quirk of MongoDB that will create objects instead of arrays when this is set to true, if there is not already an array in the database. So if you set this to true, be sure that the corresponding array property is never null or missing in the database. It must always be an array with 0 or more items.
  • preserveForm: Optional. Set to false to disable preserving of form values across hot refreshes. This can sometimes help resolve issues with sticky form values.
  • Any additional attributes are passed along to the <form> element, meaning that you can add classes, etc. When providing a boolean attribute, set it to true (no quotation marks) or a helper that returns true.

quickForm

Use this component to generate an entire form in one line. It takes and requires all the same attributes as autoForm. In addition, it recognizes the following attributes:

  • type: Two additional type values are supported: "readonly" and "disabled".
  • buttonClasses: Set the class attribute for the rendered submit button. Some templates may provide a default class if you don't set this.
  • buttonContent: The submit button content. If you don't set this, "Submit" is used. If you set this to false, no submit button is rendered.
  • fields: Optional. Bind an array or specify a comma-delimited string of field

names to include. Only the listed fields (and their subfields, if any) will be included, and they'll appear in the order you specify.

  • omitFields: Optional. Bind an array or specify a comma-delimited string of field

names to omit from the generated form. All first-level schema fields except the fields listed here (and their subfields, if any) will be included.

Any other attributes you specify will be output as attributes of the <form> element, just like when using the autoForm component. When providing a boolean attribute, set it to true (no quotation marks) or a helper that returns true.

See this demo for examples of what happens when you specify various types of fields in the fields or omitFields attributes.

afFieldInput

Renders an input control for the field. The type of control depends on what you set the type attribute to. All of the HTML5 input types plus a few more are built in. Here is the full list of included input types:

  • boolean-checkbox
  • boolean-radios
  • boolean-select
  • button
  • color
  • contenteditable
  • date
  • datetime
  • datetime-local
  • email
  • file
  • hidden
  • image
  • month
  • number
  • password
  • radio
  • range
  • reset
  • search
  • select
  • select-checkbox
  • select-checkbox-inline
  • select-multiple
  • select-radio
  • select-radio-inline
  • submit
  • tel
  • text
  • textarea
  • time
  • url
  • week

There are add-on packages that provide additional input types (widgets, UI controls).

If you don't include a type attribute, the following logic is used to automatically select an appropriate type:

  • If you supply the options attribute, a select input is used. If your schema expects an array for the field, then it is a select-multiple input. If you prefer radios or checkboxes (for example, if it is a short list of options), then add noselect=true attribute or simply set the type to select-checkbox, select-checkbox-inline, select-radio, or select-radio-inline.
  • Otherwise if the schema type is String and you include the rows attribute, a textarea is used.
  • Otherwise if the schema type is Number, a number type is used.
  • Otherwise if the schema type is Date, a date type is used.
  • Otherwise if the schema type is Boolean, the boolean-checkbox type is used. You may want to specify a type of boolean-radios or boolean-select instead. If you do so, use the trueLabel, falseLabel, and nullLabel attributes to set the labels used in the radio or select control.
  • Otherwise a text type is used.

The following attributes are recognized:

  • name: Required. The name of the schema key this field is for.
  • template (default="bootstrap3"): Specify the name of a different built-in or

custom theme template to use.

  • options: An array of options objects (see below). By specifying options, you cause the generated DOM

element to be a select element with these options, unless you also use noselect. To use the allowedValues from the schema as the options, set options="allowed". To specify a label to be displayed when there is no option selected, set firstOption="(My Select One Label)".

  • firstOption: Use with the options attribute to specify a string to use for the first option of a select input, which shows when nothing has been selected yet. For example, firstOption="(You Should Really Pick Something From This List)". There is a default first option "(Select One)". If you don't want any default option, then do firstOption=false, but make sure your select input has a default value or this will result in a confusing UX where it looks like the first option is selected but it isn't.
  • capitalize: Used only when you've set options="allowed". Set this to true

to capitalize the labels generated from allowedValues.

  • noselect: Use in conjunction with options attribute. Set this attribute

to true to render radios or checkboxes for the options instead of select.

  • trueLabel: Set to the string that should be used as the label for the true

option for an input with type boolean-select or boolean-radios.

  • falseLabel: Set to the string that should be used as the label for the false

option for an input with type boolean-select or boolean-radios.

  • nullLabel: Set to the string that should be used as the label for the empty value option for an input with type boolean-select or boolean-radios.
  • value: Set a specific, potentially reactive, value for the input. If you have also provided a doc attribute on the autoForm or quickForm, this value will override the value from the doc object.
  • defaultValue: Set a reactive default value for the input. If you have also provided a doc attribute on the autoForm or quickForm, this value will be used only when the doc object has no value for this field. This takes precedence over the defaultValue property of the field's schema. (Also, defaultValue from the schema is slightly different in that it is never used if you provide a doc attribute.)
  • Any additional attributes are passed along to the generated DOM element, meaning that you can add class, etc. When providing a boolean attribute, set it to true (no quotation marks) or a helper that returns true.
  • placeholder: As with other attributes, this will be passed along to the

generated DOM element, but you can also optionally do placeholder="schemaLabel" to use the field label defined in the schema as the input's placeholder value.

  • Each individual input type might accept and use additional attributes.

Here's an example of passing options to generate a select field:

html:

1{{> afFieldInput name="year" options=yearOptions}}

client.js:

1Template.registerHelper("yearOptions", function() {
2    return [
3        {label: "2013", value: 2013},
4        {label: "2014", value: 2014},
5        {label: "2015", value: 201