Monday, January 16, 2012

Submitting Forms via Ajax in Dart

‹prev | My Chain | next›

I had a pleasant time messing about with DartBox2D for the past couple of days. I set that aside, for the time being, to investigate writing more typical web applications with Dart..

For the sake of argument, let us assume that I was a comic book nerd back in the day. If a certain tablet had suddenly spurred me to obtain some of my old-time favorites in digital format, I might like to have a simple application to keep track of where my various comics reside.

Eventually, I will see if I can figure out how to store this on the client, but for now, I stick with a server to store the data. The simplest way (that I know) to serve up HTML, Dart and a REST-like store is an express.js application server with a node-dirty store embedded.

I already have npm installed on my system as well as express.js installed globally. The upshot of this is that I can generate a new express.js app quickly:
➜  comix git:(master) ✗ express

   create : .
   create : ./package.json
   create : ./app.js
   create : ./public
   create : ./routes
   create : ./routes/index.js
   create : ./views
   create : ./views/layout.jade
   create : ./views/index.jade
   create : ./public/javascripts
   create : ./public/images
   create : ./public/stylesheets
   create : ./public/stylesheets/style.css

   dont forget to install dependencies:
   $ cd . && npm install
I update the generated package.json to include node-dirty (a simple, nosql backend store):
{
    "name": "comic-power"
  , "version": "0.0.1"
  , "private": true
  , "dependencies": {
      "express": "2.5.2"
    , "jade": ">= 0.0.1"
    , "dirty": "0.9.5"
    , "dirty-uuid": ">= 0.0.1"
  }
}
With that, I can the use npm to install all of the dependencies for my application:
➜  comix git:(master) ✗ npm install
dirty-uuid@0.0.2 ./node_modules/dirty-uuid 
dirty@0.9.5 ./node_modules/dirty 
jade@0.20.0 ./node_modules/jade 
├── mkdirp@0.2.2
└── commander@0.2.1
express@2.5.2 ./node_modules/express 
├── mime@1.2.4
├── qs@0.4.0
├── mkdirp@0.0.7
└── connect@1.8.5
I then proceed to create a simple form to collect comic book information:


To query the values of the form to submit to the backend, I do the usual dance of adding a reference to my Dart script and a kicker to get the scripting engine started:
<script>{}</script>
<script src="scripts/comic_put.dart" type="application/dart"></script>
To query the form, I import "dart:html" and employ the query method to find and attach an event listener to the form element:
#import('dart:html');

main() {
  var form_el = document.query('#new-comic-form');

  form_el.on.submit.add((event) {
    var form = event.target
      , title = form.query('input[name=title]')
      , author = form.query('input[name=author]')
      , format = form.queryAll('input[name=format]');

    print("title: ${title.value}");
    print("author: ${author.value}");
    print(format);

    event.preventDefault();
  });
}
This results in the following console output:


I will worry about the checkboxes another day. For now, I would dearly love to submit that data to the backend. Unfortunately, the following:
    var data = {'title':title.value, 'author':author.value};
    print(JSON.stringify(data));

    var req = new XMLHttpRequest();
    req.open('post', '/comics', false);
    req.send(JSON.stringify(data));
    print(req.responseText);
Ends up causing a not-implemented error:


If I change the req.send(JSON.stringify(data)) call to just req.send(), then the request is sent... only without the data that is the whole point.

Thwarted for the moment, I call it an evening. I do very much like the query() interface for finding elements and collections of elements. Event handlers in Dart are also nice and readable. Still, it would be nice if I could submit data via XHR. I will pick back up here tomorrow.


Day #267

4 comments:

  1. I'm wondering if this is a Dartium issue. You should try building from the DartEditor and loading into Chrome(non dartium build). BTW, I do have some samples that work with XMLHttpRequest and CouchDB
    http://goo.gl/DeH7A
    http://goo.gl/uryqY
    My biggest hangup was having some obscure error message when calling setRequestHeader() before calling open(). DOMException INVALID_STATE_ERR 11, is not a very friendly error message :)

    ReplyDelete
    Replies
    1. Thanks! I definitely plan on using your work to (hopefully) get this working. I am not setting a request header like you, so I'll give that a shot. If that doesn't work, I'll try this from a local script and then fall back to frogc-ing the thing.

      It could be my version of Dartium, but it's a fairly recent build. If all else fails, I'll update/recompile.

      Delete
  2. http://src.chromium.org/viewvc/multivm/trunk/webkit/Source/WebCore/bindings/dart/custom/DartXMLHttpRequestCustom.cpp?revision=5&view=markup

    ReplyDelete
    Replies
    1. Aw, man!

      Thanks for pointing that out. Hopefully that'll get implemented soon.

      Delete