The Inevitability of the Desktop-class JavaScript Framework

Fred Brunel points out this quote from Joel Splosky late last year:

So if history repeats itself, we can expect some standardization of Ajax user interfaces to happen in the same way we got Microsoft Windows. Somebody is going to write a compelling SDK that you can use to make powerful Ajax applications with common user interface elements that work together. And whichever SDK wins the most developer mindshare will have the same kind of competitive stronghold as Microsoft had with their Windows API.

I remember reading Joel’s original post last year and agreeing very strongly with it.  I even drafted a nice long post but never had the time to polish it up.  I have no idea what SproutCore’s future will be, but I’m pretty convinced that a full cross-platform desktop-class JavaScript Framework is inevitable for the web, and Joel explains why better than I could.

30-second Tutorial on Models

To Create a New Model

In your terminal:


cd project-name
sc-gen model contacts/contact

This creates:

 

  • The model file in clients/contacts/models/contact.js
  • The unit test in clients/contacts/tests/models/contact.js
  • A fixtures file in clients/contacts/fixtures/contact.js

 

To Create Some Models

The attributes you get from the server should be simple JSON hashes.  They must have at least two properties:

 

  • type: A string identifying the model type.  By default, use the class name.  In this case “Contact”.
  • guid: A unique identifier.  This will be used to auto-merge/update records in the future.

Here is an example of some JSON data:


var records = [
  { type: "Contact", firstName: "Charles", lastName: "Jolley", guid: "contact-1", favoriteNumber: "3" }
];

 

All models are kept in an in-memory database called the Store.  To add records to the Store, you just get these data hashes from your server in whatever way you like and add them to the store like so:

SC.Store.updateRecords(records);

records should be an array of one or more data hashes.  Note that you can call this method as often as you need.  If you pass in data hashes with a type/guid matching an existing record, then the hash will simply update the record.  Otherwise, one new record instance will be found for each item.

If you want to try the following examples without having to create a new app, you can simply add some sample records to the fixtures file created in Step 1 above.  These fixtures will be auto-loaded into the Store on app load.

To Get Records

In your app, you can retrieve some records from the store using finder functions.  This call will find all the contacts in the store (this does not contact your server, it just uses whatever is in the local datastore.  You should load your records into the store first.):

var recs = Contacts.Contact.findAll();

To Edit Records

Just set and get properties on them.  If the properties are string type, you don’t even need to declare them:


var rec = Contacts.Contact.findAll()[0];
rec.set(’firstName’, ‘Joe’); // changes the firstName to Joe.

If you have a property that is not a string but some other type, you can add a line to the Contact class declaring the type:


Contacts.Contact = SC.Record.extend({
  favoriteNumberType: Number
});

Now when you get/set the favoriteNumber property, the Contact record will automatically convert it to/from a number.  This works for dates and can even work for other model objects, but that is for another tutorial.

To Save Records

You can get back out the attributes hash of a record by getting the attributes property:


var rec = Contacts.Contact.findAll().first();
var attrs = rec.get('attributes');

This will be a JSON-compliant hash that you can serialize and send back to your server in your favorite way.

Conclusion

That’s it for part 1.  There is a lot more you can do with the model layer.  As usual, the in-source docs are best and can be views on the doc viewer page.

 

Downtime

Well that was fun.  SproutCore made it on Digg today, which was cool.  But it brought down my cheap-o dreamhost shared server that I was using as a placeholder until we launched.  We are now up on the Sproutit-sponsored VDS we had planned from the beginning and everything should be available again.

Sorry for the offline!