Permalink
Switch branches/tags
Nothing to show
Find file
Fetching contributors…
Cannot retrieve contributors at this time
139 lines (94 sloc) 6.41 KB

Getting Started: Part 2

After reading this guide you will be able to:

  • Define your models using SC.Record.
  • Manage your models using SC.Store.
  • Load data into the store from fixture data.
  • Query your models using SC.Query.

endprologue.

Prepare the Application

In the first part of this guide, you learned how to build a basic Todo application. You now know how to define your models, views, and controllers, then describe how they interact via bindings. So far, however, you have had no way to persist the information between page refreshes.

The best way to change that is to use SproutCore’s Data Store framework to manage records. An instance of SC.Store is responsible for managing the lifecycle of your records. Behind the scenes, the store uses an SC.DataSource to translate retrieve data from your server and persist changes back.

If you still have your Todo application from the first part of this guide, use that. If not, you can get a completed version from GitHub.

Now that we’ll be using the Data Store, we need to tell SproutCore to include it when your run your application. You can add this dependency in the Buildfile. Just change config line to:

config :all,¬
:required => [“sproutcore/core_foundation”, “sproutcore/datastore”], ¬
:theme => “sproutcore/empty_theme”

Defining the Model

The first thing that we need to modify in code is Todos.Todo. Currently it’s just a subclass of SC.Object. Let’s change it to SC.Record:

Todos.Todo = SC.Record.extend({
title: SC.Record.attr(String),
isDone: SC.Record.attr(Boolean, { defaultValue: NO })
});

Now we are subclassing SC.Record instead of SC.Object. We also add attributes definitions: title always gets converted to a String, and isDone becomes a Boolean. Additionally isDone will default to NO if you don’t provide a different value when creating a new record. If you want to read more about how records work, check out the records guide.

Creating Fixture Data

The easiest way to start development without having to connect to a backend server is to use fixtures. With fixtures, we provide an array of data hashes that represent each record. Let’s create a few fixtures below the record definition:

Todos.Todo.FIXTURES = [

{ “guid”: “todo-1”, “title”: “Build my first SproutCore app”, “isDone”: false }, { “guid”: “todo-2”, “title”: “Build a really awesome SproutCore app”, “isDone”: false }, { “guid”: “todo-3”, “title”: “Next, the world!”, “isDone”: false }

];

Now we have a model and some sample data, but if you run the application, nothing happens. What’s wrong?

Remember that an instance of SC.Store is responsible for loading records, and that includes fixture data. We will also need to tell the controller exactly which data we want to fetch from that store. Let’s start by adding a store to Todos application:

// add store property to previously created Todos object
Todos = SC.Application.create({
store: SC.Store.create().from(SC.Record.fixtures)
});

We just created a new SC.Store and told it to load its data from the fixtures we previously defined. Later in the development cycle, when you want to connect your application to a real server, you can just change the argument
of the from() method to something like “MyDataSource”.

Let’s make sure that everything is working. If you haven’t already, run sc-server from your application directory, then open http://localhost:4020/todos in your web browser. Open your browser’s JavaScript console and type the following commands:

records = Todos.store.find(Todos.Todo)
records.objectAt(0).get(‘title’)
// => “Build my first SproutCore app”

We just used the store’s find() method to return all records of a certain type. This will return an instance of SC.RecordArray that contains all of Todos.Todo records the store knows about. If you create a new Todo record in the future, it will automatically be added to the record array. Conversely, if you were to ever destroy one of your Todo objects, it would be automatically removed.

Connecting the Pieces

Now you’re ready to bind your controller to the store. In order to do that, you’ll need to set content property of Todos.todoListController to a record array that you will fetch with SC.Store.find() function. You can do it in the SC.ready callback, which is already defined at the end of your todos.js file:

SC.ready(function() {
Todos.mainPane = SC.TemplatePane.append({
layerId: ‘todos’,
templateName: ‘todos’
});

var todos = Todos.store.find(Todos.Todo); Todos.todoListController.set(‘content’, todos);

});

Now refresh the page and you should see that all of the todos from fixtures are displayed in the view.

Next, we need to make sure that the store knows about new records. Update the controller’s createTodo method to use SC.Store’s createRecord method:

createTodo: function(title) { Todos.store.createRecord(Todos.Todo, { title: title }); },

Last, our clearCompletedTodos function needs to be updated to utilize the destroy method available on SC.Record:

// updating existing code Todos.todoListController = SC.ArrayController.create({ // … clearCompletedTodos: function(){ this.filterProperty(‘isDone’, true).forEach( function(item) { item.destroy(); }); }, // … )};

Try reloading a page and adding a new todo, marking a few as done and clicking the “Clear Completed Todos” button. It should automatically place new one at the bottom of the list and clear any completed when you click the button. All of the other operations that you perform on records should also work seamlessly, because we use standard get() and set() functions that work for every type of objects in SproutCore.

Changelog