<commit_before>AutoForm
=========================

[![Build Status](https://travis-ci.org/aldeed/meteor-autoform.svg)](https://travis-ci.org/aldeed/meteor-autoform)

AutoForm is a smart package for Meteor that adds UI components and helpers to easily
create basic forms with automatic insert and update events, and automatic
reactive validation. This package requires and automatically installs the
[simple-schema](https://github.com/aldeed/meteor-simple-schema) package.
You can optionally use it with the
[collection2](https://github.com/aldeed/meteor-collection2) package, which you
have to add to your app yourself.

## Table of Contents
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
**Table of Contents**  *generated with [DocToc](http://doctoc.herokuapp.com/)*

- [Installation](#installation)
- [Demo](#demo)
- [Example](#example)
  - [A Basic Insert Form](#a-basic-insert-form)
  - [A Basic Update Form](#a-basic-update-form)
  - [A Custom Insert Form](#a-custom-insert-form)
  - [Another Custom Insert Form](#another-custom-insert-form)
- [Component and Helper Reference](#component-and-helper-reference)
  - [autoForm](#autoform)
  - [quickForm](#quickform)
  - [afFieldInput](#affieldinput)
  - [afFieldSelect](#affieldselect)
  - [afFieldMessage](#affieldmessage)
  - [afFieldIsInvalid](#affieldisinvalid)
  - [afFormGroup](#afformgroup)
  - [afQuickField](#afquickfield)
    - [afQuickField Examples](#afquickfield-examples)
  - [afFieldValueIs](#affieldvalueis)
  - [afFieldValueContains](#affieldvaluecontains)
  - [afFieldNames](#affieldnames)
  - [afQuickFields](#afquickfields)
- [Objects and Arrays](#objects-and-arrays)
  - [afObjectField](#afobjectfield)
  - [afArrayField](#afarrayfield)
  - [afEachArrayItem](#afeacharrayitem)
  - [afArrayFieldIsFirstVisible and afArrayFieldIsLastVisible](#afarrayfieldisfirstvisible-and-afarrayfieldislastvisible)
- [Public API](#public-api)
- [Non-Collection Forms](#non-collection-forms)
  - [An Example Contact Form](#an-example-contact-form)
- [Fine Tuning Validation](#fine-tuning-validation)
- [Manual Validation](#manual-validation)
- [Resetting Validation](#resetting-validation)
- [The Form Document](#the-form-document)
  - [Getting Current Field Values](#getting-current-field-values)
- [Callbacks/Hooks](#callbackshooks)
  - [onSubmit](#onsubmit)
  - [formToDoc and docToForm](#formtodoc-and-doctoform)
- [Putting Field Attribute Defaults in the Schema](#putting-field-attribute-defaults-in-the-schema)
- [Complex Schemas](#complex-schemas)
- [Complex Controls](#complex-controls)
- [Dates](#dates)
  - [type=date](#type=date)
  - [type=datetime](#type=datetime)
  - [type=datetime-local](#type=datetime-local)
- [Templates](#templates)
  - [Using a Different Template](#using-a-different-template)
  - [Creating a Custom Template](#creating-a-custom-template)
- [Making AutoForm-Ready Components](#making-autoform-ready-components)
- [Common Questions](#common-questions)
  - [Should the value of `schema` and `collection` have quotation marks around it?](#should-the-value-of-schema-and-collection-have-quotation-marks-around-it)
  - [Which components should I use?](#which-components-should-i-use)
  - [Can I reuse the same `quickForm` or `autoForm` for both inserts and updates?](#can-i-reuse-the-same-quickform-or-autoform-for-both-inserts-and-updates)
  - [What are the various ways I can specify options for a select, radio group, or checkbox group?](#what-are-the-various-ways-i-can-specify-options-for-a-select-radio-group-or-checkbox-group)
    - [Use allowed values array from the schema as both the label and the value](#use-allowed-values-array-from-the-schema-as-both-the-label-and-the-value)
    - [Set options in the schema](#set-options-in-the-schema)
    - [Calculate options in the schema](#calculate-options-in-the-schema)
    - [Use a helper](#use-a-helper)
  - [Can I put HTML in my error messages?](#can-i-put-html-in-my-error-messages)
- [Examples](#examples)
- [Troubleshooting](#troubleshooting)
- [Contributing](#contributing)

<!-- END doctoc generated TOC please keep comment here to allow auto update -->

## Installation

In a Meteor app directory, enter:

```
$ meteor add aldeed:autoform
```

## Demo

[Live](http://autoform.meteor.com)

[Source](https://github.com/aldeed/autoform-demo)

## 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` for this example
to work.)

```js
Books = new Mongo.Collection("books");
Books.attachSchema(new SimpleSchema({
  title: {
    type: String,
    label: "Title",
    max: 200
  },
  author: {
    type: String,
    label: "Author"
  },
  copies: {
    type: Number,
    label: "Number of copies",
    min: 0
  },
  lastCheckedOut: {
    type: Date,
    label: "Last date this book was checked out",
    optional: true
  },
  summary: {
    type: String,
    label: "Brief summary",
    optional: true,
    max: 1000
  }
}));
```

### A Basic Insert Form

```html
<template name="insertBookForm">
  {{> quickForm collection="Books" id="insertBookForm" type="insert"}}
</template>
```

That's it! This gives you:

* An autogenerated form that uses bootstrap3 classes.
* 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 "Books" collection schema. 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:

```html
<template name="updateBookForm">
  {{> quickForm collection="Books" doc=editingDoc id="updateBookForm" type="update"}}
</template>
```

And the helper:

```js
Template.updateBookForm.helpers({
  editingDoc: function editingDocHelper() {
    return Books.findOne({_id: Session.get("selectedDocId")});
  }
});
```

### 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:

```html
<template name="insertBookForm">
  {{#autoForm collection="Books" id="insertBookForm" type="insert"}}
    <fieldset>
      <legend>Add a Book</legend>
      {{> afQuickField name='title'}}
      {{> afQuickField name='author'}}
      {{> afQuickField name='summary' rows=6}}
      {{> afQuickField name='copies'}}
      {{> afQuickField name='lastCheckedOut'}}
    </fieldset>
    <button type="submit" class="btn btn-primary">Insert</button>
  {{/autoForm}}
</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
* afFieldSelect
* afFieldMessage

Here's an example:

```html
<template name="insertBookForm">
  {{#autoForm collection="Books" id="insertBookForm" type="insert"}}
  <fieldset>
    <legend>Add a Book</legend>
    {{> afQuickField name='title'}}
    {{> afQuickField name='author'}}
    {{> afQuickField name='summary' rows=6}}
    {{> afQuickField name='copies'}}
    {{> afQuickField name='lastCheckedOut'}}
    <div class="form-group {{#if afFieldIsInvalid name='cost'}}has-error{{/if}}">
      <div class="input-group">
        <span class="input-group-addon">$</span>
        {{> afFieldInput name='cost'}}
        <span class="input-group-addon">/each</span>
      </div>
      {{#if afFieldIsInvalid name='cost'}}
      <span class="help-block">{{afFieldMessage name='cost'}}</span>
      {{/if}}
    </div>
  </fieldset>
  <button type="submit" class="btn btn-primary">Insert</button>
  {{/autoForm}}
</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

### 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 slightly different schema for the form than
the one your collection uses. However, the final object will still have to pass
validation when `insert` or `update` is called on the collection. Set to one of the following:
    * The name of a helper function (no quotation marks) that returns an
instance of `SimpleSchema`.<commit_msg>link to new delete button pkg; closes #373<commit_after>AutoForm
=========================

[![Build Status](https://travis-ci.org/aldeed/meteor-autoform.svg)](https://travis-ci.org/aldeed/meteor-autoform)

AutoForm is a smart package for Meteor that adds UI components and helpers to easily
create basic forms with automatic insert and update events, and automatic
reactive validation. This package requires and automatically installs the
[simple-schema](https://github.com/aldeed/meteor-simple-schema) package.
You can optionally use it with the
[collection2](https://github.com/aldeed/meteor-collection2) package, which you
have to add to your app yourself.

## Table of Contents
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
**Table of Contents**  *generated with [DocToc](http://doctoc.herokuapp.com/)*

- [Installation](#installation)
- [Demo](#demo)
- [Example](#example)
  - [A Basic Insert Form](#a-basic-insert-form)
  - [A Basic Update Form](#a-basic-update-form)
  - [A Custom Insert Form](#a-custom-insert-form)
  - [Another Custom Insert Form](#another-custom-insert-form)
- [Component and Helper Reference](#component-and-helper-reference)
  - [autoForm](#autoform)
  - [quickForm](#quickform)
  - [afFieldInput](#affieldinput)
  - [afFieldSelect](#affieldselect)
  - [afFieldMessage](#affieldmessage)
  - [afFieldIsInvalid](#affieldisinvalid)
  - [afFormGroup](#afformgroup)
  - [afQuickField](#afquickfield)
    - [afQuickField Examples](#afquickfield-examples)
  - [afFieldValueIs](#affieldvalueis)
  - [afFieldValueContains](#affieldvaluecontains)
  - [afFieldNames](#affieldnames)
  - [afQuickFields](#afquickfields)
- [Objects and Arrays](#objects-and-arrays)
  - [afObjectField](#afobjectfield)
  - [afArrayField](#afarrayfield)
  - [afEachArrayItem](#afeacharrayitem)
  - [afArrayFieldIsFirstVisible and afArrayFieldIsLastVisible](#afarrayfieldisfirstvisible-and-afarrayfieldislastvisible)
- [Public API](#public-api)
- [Non-Collection Forms](#non-collection-forms)
  - [An Example Contact Form](#an-example-contact-form)
- [Fine Tuning Validation](#fine-tuning-validation)
- [Manual Validation](#manual-validation)
- [Resetting Validation](#resetting-validation)
- [The Form Document](#the-form-document)
  - [Getting Current Field Values](#getting-current-field-values)
- [Callbacks/Hooks](#callbackshooks)
  - [onSubmit](#onsubmit)
  - [formToDoc and docToForm](#formtodoc-and-doctoform)
- [Putting Field Attribute Defaults in the Schema](#putting-field-attribute-defaults-in-the-schema)
- [Complex Schemas](#complex-schemas)
- [Complex Controls](#complex-controls)
- [Dates](#dates)
  - [type=date](#type=date)
  - [type=datetime](#type=datetime)
  - [type=datetime-local](#type=datetime-local)
- [Templates](#templates)
  - [Using a Different Template](#using-a-different-template)
  - [Creating a Custom Template](#creating-a-custom-template)
- [Making AutoForm-Ready Components](#making-autoform-ready-components)
- [Common Questions](#common-questions)
  - [Should the value of `schema` and `collection` have quotation marks around it?](#should-the-value-of-schema-and-collection-have-quotation-marks-around-it)
  - [Which components should I use?](#which-components-should-i-use)
  - [Can I reuse the same `quickForm` or `autoForm` for both inserts and updates?](#can-i-reuse-the-same-quickform-or-autoform-for-both-inserts-and-updates)
  - [What are the various ways I can specify options for a select, radio group, or checkbox group?](#what-are-the-various-ways-i-can-specify-options-for-a-select-radio-group-or-checkbox-group)
    - [Use allowed values array from the schema as both the label and the value](#use-allowed-values-array-from-the-schema-as-both-the-label-and-the-value)
    - [Set options in the schema](#set-options-in-the-schema)
    - [Calculate options in the schema](#calculate-options-in-the-schema)
    - [Use a helper](#use-a-helper)
  - [Can I put HTML in my error messages?](#can-i-put-html-in-my-error-messages)
- [Examples](#examples)
- [Troubleshooting](#troubleshooting)
- [Contributing](#contributing)

<!-- END doctoc generated TOC please keep comment here to allow auto update -->

## Installation

In a Meteor app directory, enter:

```
$ meteor add aldeed:autoform
```

## Demo

[Live](http://autoform.meteor.com)

[Source](https://github.com/aldeed/autoform-demo)

## 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` for this example
to work.)

```js
Books = new Mongo.Collection("books");
Books.attachSchema(new SimpleSchema({
  title: {
    type: String,
    label: "Title",
    max: 200
  },
  author: {
    type: String,
    label: "Author"
  },
  copies: {
    type: Number,
    label: "Number of copies",
    min: 0
  },
  lastCheckedOut: {
    type: Date,
    label: "Last date this book was checked out",
    optional: true
  },
  summary: {
    type: String,
    label: "Brief summary",
    optional: true,
    max: 1000
  }
}));
```

### A Basic Insert Form

```html
<template name="insertBookForm">
  {{> quickForm collection="Books" id="insertBookForm" type="insert"}}
</template>
```

That's it! This gives you:

* An autogenerated form that uses bootstrap3 classes.
* 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 "Books" collection schema. 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:

```html
<template name="updateBookForm">
  {{> quickForm collection="Books" doc=editingDoc id="updateBookForm" type="update"}}
</template>
```

And the helper:

```js
Template.updateBookForm.helpers({
  editingDoc: function editingDocHelper() {
    return Books.findOne({_id: Session.get("selectedDocId")});
  }
});
```

### 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:

```html
<template name="insertBookForm">
  {{#autoForm collection="Books" id="insertBookForm" type="insert"}}
    <fieldset>
      <legend>Add a Book</legend>
      {{> afQuickField name='title'}}
      {{> afQuickField name='author'}}
      {{> afQuickField name='summary' rows=6}}
      {{> afQuickField name='copies'}}
      {{> afQuickField name='lastCheckedOut'}}
    </fieldset>
    <button type="submit" class="btn btn-primary">Insert</button>
  {{/autoForm}}
</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
* afFieldSelect
* afFieldMessage

Here's an example:

```html
<template name="insertBookForm">
  {{#autoForm collection="Books" id="insertBookForm" type="insert"}}
  <fieldset>
    <legend>Add a Book</legend>
    {{> afQuickField name='title'}}
    {{> afQuickField name='author'}}
    {{> afQuickField name='summary' rows=6}}
    {{> afQuickField name='copies'}}
    {{> afQuickField name='lastCheckedOut'}}
    <div class="form-group {{#if afFieldIsInvalid name='cost'}}has-error{{/if}}">
      <div class="input-group">
        <span class="input-group-addon">$</span>
        {{> afFieldInput name='cost'}}
        <span class="input-group-addon">/each</span>
      </div>
      {{#if afFieldIsInvalid name='cost'}}
      <span class="help-block">{{afFieldMessage name='cost'}}</span>
      {{/if}}
    </div>
  </fieldset>
  <button type="submit" class="btn btn-primary">Insert</button>
  {{/autoForm}}
</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](https://github.com/aldeed/meteor-delete-button).

### 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 slightly different schema for the form than
the one your collection uses. However, the final object will still have to pass
validation when `insert` or `update` is called on the collection. Set to one of the following:
    * The name of a helper function (no quotation marks) that returns an
instance of `SimpleSchema`.
{'fraction_non_alphanumeric': 0.13001912045889102, 'fraction_numerical': 0.0019623628861829526, 'mean_word_length': 4.510119212642085, 'pattern_counts': {'":': 0, '<': 71, '<?xml version=': 0, '>': 97, 'https://': 11, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2572353', 'n_tokens_mistral': 6219, 'n_tokens_neox': 5851, 'n_words': 1942}