-
Notifications
You must be signed in to change notification settings - Fork 0
Hello World Tutorial 4: Observers
So far you have installed SproutCore, created your first app, add a label view, setup a controller, some bindings and button. Now we’re going to move onto one of the most advanced topics of SproutCore that gives it so much of its power.
A useful as bindings are, bindings are actually a special case of a more powerful feature in SproutCore called Key Value Observing, or KVO. KVO simply means that you can usually tell any SproutCore object to notify you whenever one of its properties change. For example, you might have a model object with a firstName and a lastName, and if your controller is observing those two properties, then a method on that controller will be called anytime one of those properties changes.
Observing is a powerful way to monitor the state of your application and respond to changes in it. Often times when you write a class, you will actually define a number of properties on it that you expect other object to change on it. Then you write observers that will be notified when those properties change and act accordingly. In fact, that is exactly what you are going to do now.
Before we created a button that would simply trigger an action whenever it was pressed. But buttons can actually be used in another way to represent a state such as on or off. We’re going to convert our button to checkbox and then use that to determine which label to show. To do that, we want to define another property on the controller called “isClockShowing”. Just after the method you added, insert a comma and then this line:
isClockShowing: NO
SproutCore defines two constants, YES and NO that mean true and false respectively. These constants are used throughout the framework because they often make code more readable. If you prefer true and false you can use those instead.
Now that we have a property, let’s write a simple observer. This observer will just change the value of the greeting for now. Add a comma after the “NO” and type:
isClockShowingObserver: function() {
var isClockShowing = this.get('isClockShowing') ;
var newGreeting = (isClockShowing) ? 'CLOCK!' : 'Hello World!' ;
this.set('greeting', newGreeting) ;
}.observes('isClockShowing')
Notice the little function call we inserted at the end of the declaration? This is how we tell SproutCore that a particular method should observe some property. In this case, the function we just defined will observe the isClockShowing property on the receiver. You can use observers to observe practically any object you like just by naming the path.
To test this out, try refreshing in the Firefox and in Firebug type the following:
HelloWorld.appController.set('isClockShowing', YES)
Pretty cool, huh?
A BRIEF ASIDE ABOUT GET AND SET: You may haven noticed in the code you are writing here that instead of using just foo.bar and foo.bar = X, we’re using these methods get() and set(). get() and set() are an important part of SproutCore because they give SproutCore a chance to notify observers whenever properties have changed, among other things. They also allow something called computed properties that make it possible to write functions masquerading as static properties. In general, whenever you want to get a property that does not begin with an underscore, you should use get() and set(). Properties whose names begin with an underscore (like _myProperty), are considered private to the object and hence NOT observable. |
OK, now that we have our observer working, let’s setup the checkbox to use it. Back in the main_page.js, replace the button view in the childViews attribute line and replace it with “checkboxView”. Then delete the buttonView declaration and replace it with the following:
checkboxView: SC.CheckboxView.design({
layout: { centerX: 0, centerY: 20, width: 250, height: 18 },
title: "Show Clock",
valueBinding: "HelloWorld.appController.isClockShowing"
})
The checkbox’ value property is now bound to the isClockShowing property, which means whenever you click the checkbox, the isClockShowing property will update causing your observer to fire which will change the greeting property and update the label. It all works like magic we hope. Refresh the web browser and try it out.
Its time to add the clock function itself. This simply requires some changes to the controller. We’re going to make use of SproutCore Timers here, which provide a much more efficient way to schedule code execution that timeouts, as well as from formatting functions added to Date by SproutCore. Start by adding the following two methods to your controller (be sure to add a comma after the last method first):
tick: function() {
this.set('greeting', this.now()) ;
},
now: function() {
return new Date().format('hh:mm:ss');
}
Now, edit the contents of the isClockShowingObserver to be the following:
isClockShowingObserver: function() {
var isClockShowing = this.get('isClockShowing') ;
// create a timer if it does not exist already
if (!this._timer) this._timer = SC.Timer.schedule({
target: this, action: 'tick', repeats: YES, interval: 1000
});
// pause the timer unless the clock is showing
this._timer.set('isPaused', !isClockShowing) ;
// update right now
var newGreeting = (isClockShowing) ? this.now() : 'Hello World';
this.set('greeting', newGreeting) ;
}.observes('isClockShowing'),
Refresh the page and try clicking the checkbox your clock should be working now.
Finally add some CSS styles to your app. Go to main_page.js and change the width of both views to 300, the height of the labelView to 50 and the checkboxView centerY to 30. At the end of the mainPane declaration add .classNames(clock), this will add the classname clock to the app main pane. The mainPane declaration should be:
mainPane: SC.MainPane.design({
childViews: 'labelView checkboxView'.w(),
labelView: SC.LabelView.design({
layout: { centerX: 0, centerY: 0, width: 300, height: 50 },
valueBinding: "HelloWorld.appController.greeting"
}),
checkboxView: SC.CheckboxView.design({
layout: { centerX: 0, centerY: 30, width: 300, height: 18 },
title: "Show Clock",
valueBinding: "HelloWorld.appController.isClockShowing"
})
}).classNames('clock')
Create a new css file called clock.css and copy the following code:
.clock {
background: black;
color: white;
}
.sc-theme .clock .sc-label-view {
font-size: 48px;
line-height: 1.0;
}
That’s it. Refresh the page and try clicking the checkbox. Not bad for a few minutes work.
Thanks!
This concludes the first tutorial for SproutCore. You’ve had a brief introduction to the major concepts of SproutCore including bindings, observers, controllers, views, and view helpers. You are now ready to check out the example code and start building some apps. Here are some resources to help get you started:
Reference documentation for all of the SproutCore classes is available from your test server by visiting http://localhost:4020/sproutcore/-docs (click Rebuild Docs to get the documents the first time). You can also view a recent version of the docs online at the SproutCore site if you prefer.
Also, don’t forget to get involved in the SproutCore community. There are plenty of folks (including the authors of the framework) who are happy to help.
Good luck and happy Sprouting!
edit this page to add comments here