The official documentation has moved to http://docs.couchdb.org — The transition is not 100% complete, but http://docs.couchdb.org should be seen as having the latest info. In some cases, the wiki still has some more or older info on certain topics inside CouchDB.

You need to be added to the ContributorsGroup to edit the wiki. But don't worry! Just email any Mailing List or grab us on IRC and let us know your user name.

CouchDB supports HTML forms in a number of ways. Some useful HTML5 references are html5rocks and the definitive Forms in HTML and the Form element.

Forms without client-side Javascript

A standard form and submit can be handled by CouchDB by using Document_Update_Handlers to capture and process the POSTed data.

A minimal HTML5 form

<!DOCTYPE html>

<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Minimal Form</title>
</head>

<body>
  <div id="contact-form">
    <form id="contact" method="post" action="/db/_design/ddoc/_update/simpleform">
      <fieldset>
        <label for="name">name</label>    <input type="text" name="name" placeholder="Full Name" title="Enter your name" class="required">
        <label for="phone">phone</label>  <input type="tel" name="phone" placeholder="+1 (555) 555-5555" required="" pattern="\+?[0-9 )(-]+">
        <label for="email">e-mail</label> <input type="email" name="email" placeholder="you@example.org" title="e-mail address" class="required email">
        <label for="blog">blog</label>    <input type="url" name="url" placeholder="http://">
        <label for="message">message</label>
        <textarea name="message"></textarea>
        <input type="submit" name="submit" class="button" id="submit" value="submit">
      </fieldset>
    </form>
  </div>
</body>
</html>

The most important part of the above form is the action="/simpleform/_design/simpleform/_update/simpleform" which specifies the update handler that will receive the POSTed data.

It's broken down into 5 key sections:

Submitting the form from the terminal

Likely you'll be fiddling with your form quite a bit while working on the update handler. In this case it makes a lot of sense simply to drive the form directly from the command line. There is more information at Commandline_CouchDB, including Windows tips.

curl -vX POST http://localhost:5984/simpleform/_design/simpleform/_update/simpleform \
    --header Content-Type:application/x-www-form-urlencoded \
    --data-urlencode name="John Doe" \
    --data-urlencode email="john@example.org" \
    --data-urlencode phone="+1 (234) 567-890" \
    --data-urlencode url="http://example.org/blog" \
    --data-urlencode message="Y U NO HAZ CHEESBURGER" \
    --data-urlencode submit="submit"

If you are on a unix-like system, you may enjoy the colour output afforded by httpie, a python-based curl replacement:

http --pretty --verbose --style fruity --form \
    post http://localhost:5984/simpleform/_design/simpleform/_update/simpleform  \
    name="John Doe" \
    email="john@example.org" \
    phone="+1 (234) 567-890" \
    url="http://example.org/blog" \
    message="Y U NO HAZ CHEESBURGER" \
    submit="submit"

A basic update handler

Here's a simple update handler that will receive the POSTed data as second parameter, and the previous document version if any as the first parameter . In our case, using POST, there will be no existing document so this will always be null. Finally this function, to help us debug the handler, conveniently returns the output of the new document, along with the request and previous doc if any. Obviously this could be HTML or a redirect to another page using custom headers, you will need to customise this to fit.

function(previous, request) {

    /* during development and testing you can write data to couch.log
     log({"previous": previous})
     log({"request": request})
    */

    var doc = {}

    if (!previous) {
        // there's no existing document _id as we are not using PUT
        // let's use the email address as the _id instead
        if (request.form && request.form.email) {
            // Extract the JSON-parsed form from the request
            // and add in the user's email as docid
           doc     = request.form
           doc._id = request.form.email
        }
    }
    return [doc, toJSON({"request": request, "previous": previous, "doc": doc})]
}

Tips and Tricks

There are a few points to cover here:

Results from the form

After filling out the form and POSTing it back, you'll receive the results from toJSON in your browser. You can use firebug or chrome developer tools to view the resulting text in a pretty JSON format, or copy and paste it into a terminal and use any of the JSON prettifiers out there, such as yajl, which also has a json_reformat command distributed with it.

Let's take a look in more detail over the three sections returned. The first section request.info is simply the current DB information, identical to GET $COUCH/db_name.

{
  request: {
    info: {
      db_name: "simpleform",
      doc_count: 3,
      doc_del_count: 0,
      update_seq: 32,
      purge_seq: 0,
      compact_running: false,
      disk_size: 340069,
      data_size: 158491,
      instance_start_time: "1340837365780629",
      disk_format_version: 6,
      committed_update_seq: 32
    },

    id: null,
    uuid: "8363428f19b4bc21217044e2b30133ad",
    method: "POST",
    requested_path: ["simpleform", "_design", "simpleform", "_update", "simpleform"],
    path: ["simpleform", "_design", "simpleform", "_update", "simpleform"],
    raw_path: "/simpleform/_design/simpleform/_update/simpleform",
    query: {},
    headers: {
      Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
      Accept - Charset: "ISO-8859-1,utf-8;q=0.7,*;q=0.3",
      Accept - Encoding: "gzip,deflate,sdch",
      Accept - Language: "en-US,en;q=0.8",
      Cache - Control: "max-age=0",
      Connection: "keep-alive",
      Content - Length: "150",
      Content - Type: "application/x-www-form-urlencoded",
      Host: "localhost:5984",
      Origin: "http://localhost:5984",
      Referer: "http://localhost:5984/simpleform/_design/simpleform/minimalform.html",
      User - Agent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_4) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1188.0 Safari/537.1"
    },

    body: "name=John+Doe&phone=%2B1+%28234%29+987-654&email=john%40example.org&url=http%3A%2F%2Fjohn.blogger.com%2F&message=STILL+NO+CHEEZBURGER%3F&submit=submit",
    peer: "127.0.0.1",
    form: {
      name: "John Doe",
      phone: "+1 (234) 987-654",
      email: "john@example.org",
      url: "http://john.blogger.com/",
      message: "STILL NO CHEEZBURGER?",
      submit: "submit",
      _id: "john@example.org"
    },

    cookie: {},
    userCtx: {
      db: "simpleform",
      name: null,
      roles: []
    },
    secObj: {}
  },
  previous: null,

Emitting the result during testing

Finally we emit the resulting document, after our server-side update handler has run. Note that the revision _rev is not yet available, but as noted in Document_Update_Handlers it is possible to retrieve this.

  doc: {
    name: "John Doe",
    phone: "+1 (234) 987-654",
    email: "john@example.org",
    url: "http://john.blogger.com/",
    message: "STILL NO CHEEZBURGER?",
    submit: "submit",
    _id: "john@example.org"
  }
}

Retrieve the Document

After the write was successful we can retrieve the new document:

$ curl --silent -HContent-Type:application/json  -vXGET http://localhost:5984/simpleform/john@example.org | json_reformat

* About to connect() to localhost port 5984 (#0)
*   Trying ::1... Connection refused
*   Trying 127.0.0.1... connected
* Connected to localhost (127.0.0.1) port 5984 (#0)
> GET /simpleform/john@example.org HTTP/1.1
> User-Agent: curl/7.21.4 (universal-apple-darwin11.0) libcurl/7.21.4 OpenSSL/0.9.8r zlib/1.2.5
> Host: localhost:5984
> Accept: */*
> Content-Type:application/json
>
< HTTP/1.1 200 OK
< Server: CouchDB/1.3.0a- (Erlang OTP/R15B01)
< ETag: "1-5c316da64caebbebcd0f87364df2a0e7"
< Date: Thu, 28 Jun 2012 11:31:49 GMT
< Content-Type: text/plain; charset=utf-8
< Content-Length: 228
< Cache-Control: must-revalidate
<
{ [data not shown]
* Connection #0 to host localhost left intact
* Closing connection #0
{
    "_id": "john@example.org",
    "_rev": "1-5c316da64caebbebcd0f87364df2a0e7",
    "name": "John Doe",
    "phone": "+1 (234) 987-654",
    "email": "john@example.org",
    "url": "http://john.blogger.com/",
    "message": "STILL NO CHEEZBURGER?",
    "submit": "submit"
}

With the basic update handler above you should have no trouble modifying it further to perform redirects, extract/merge or modify the data available to you - new and old document versions, and user/security context as well. Don't forget that some code is better in a Document_Update_Validation rather than in the update handler. The update handler will always act as another HTTP POST/PUT, just run conveniently inside the server. They can still suffer from document conflicts, for example.

Working_with_Forms (last edited 2012-06-28 11:40:58 by DaveCottlehuber)