• If you are citizen of an European Union member nation, you may not use this service unless you are at least 16 years old.

  • You already know Dokkio is an AI-powered assistant to organize & manage your digital files & messages. Very soon, Dokkio will support Outlook as well as One Drive. Check it out today!

View
 

Hello World Tutorial 2: Your First Views

Page history last edited by Richard Klancer 13 years, 7 months ago

In the last tutorial you installed SproutCore and created your first application. Now we are going to add some views.

Views are JavaScript classes that manage part of your web page for you. They create DOM elements, handle events, perform animation and lots of other useful things. In fact, in SproutCore you will not work with HTML or the DOM directly unless you are writing a custom view. Instead, you should let the SproutCore view classes handle it for you.

 

Although views are JavaScript, they have an HTML component to them also, of course. Rather than make you write some HTML and JavaScript to build your views, SproutCore comes with a useful set of view classes and utilities that will help you to layout your application. This can make your life much easier when it comes to designing the visual part of your application.

 

So let’s get started adding your first view.

 

Step 1. Take a Tour of Your App

 

All CSS , images and other static resources for an app are stored inside a folder called “resources”. They are stored here because SproutCore supports localization. You can add lproj directories for virtually any language you like, and SproutCore will handle building that language for you.

 

The default language, however, is usually english. To make things easy, you usually put common resources shared by all languages in this folder as well.

 

If you open the folder in apps/hello_world/resources/ you will find a file called loading.rhtml. This is the file that contains the body HTML that will be displayed when your page loads. The extension is rhtml because it uses a templating language called Erubis that is based on Ruby. You do not need to know Ruby to edit it; you can just insert plain html.

 

Any HTML in this file will be visible on screen while your page loads its application JavaScript. SproutCore applications are optimized for caching and startup very fast, so your users will often only see this content for a brief moment on their first app load, if at all.

 

There are two other files inside resources: string.js which will contain all the strings necessary for localization purposes and main_page.js, which describes the main user interface for your application.

 

At the app root level you have core.js and main.js. The former contains all your global variables and initial app setup. The latter will start your app running (as you develop your application you will probably modify this file to do some initial controller setup.)

 

Step 2. Modify your first View

 

Open the main_page.js file in apps/hello_world/resources/ and replace the text inside layout and value of labelView as follows:

 

          layout: { centerX: 0, centerY: 0, width: 400, height: 18 },

          value: "Hello World! I'm Using Sproutcore"

 

Now reload the page and you should see the phrase “Hello World! I’m Using Sproutcore” . If you see this, congratulations, you’ve modified your first view. If you don't, clear your browser cache, and then try again.

 

Step 3. Add a Controller

 

Of course, just displaying some text doesn’t really require JavaScript. Let’s do something more interesting. Most of the actual JavaScript you write will be held in controller objects. These are JavaScript objects that control your views and your model data. To do anything useful with our label view, we first need a controller to play with, so open your terminal again so that you are in the root project directory (the one with the apps folder) and type:

 

sc-gen controller HelloWorld.appController

 

This will create a controller in the hello_world application named HelloWorld.appController. Go open the file that was created at apps/hello_world/controllers/app.js. You should see something like this:

 

HelloWorld.appController = SC.ObjectController.create(
/** @scope HelloWorld.appController.prototype */ {
// TODO: Add your own code here. 
}) ;

 

This is a controller class. The create() method is what you use to create a new object. Unlike most object-oriented systems, SproutCore makes it really easy to create custom objects. Instead of creating constructor methods with different parameters, you create a SproutCore object just by calling create() and setting the properties you want directly on the new object. This is much faster in JavaScript and more convenient for building JavaScript applications than forcing you to write constructor methods all the time.

 

For this controller, we need to add a property that will contain the string we want to display on screen. Replace the line that says “// TODO: ...” with the following:

 

greeting: "Hello World!"

 

Step 4. Add A Binding

 

Now switch back to your main_page.js and replace the labelView value with a valueBinding so that now it looks like this instead:

 

labelView: SC.LabelView.design({
  layout: { centerX: 0, centerY: 0, width: 400, height: 18 },
  textAlign: SC.ALIGN_CENTER,
  tagName: 'h1', 
  valueBinding: 'HelloWorld.appController.greeting'
})

 

If you hit refresh now on your web browser, you should still see “Hello World!” but now it is coming from the controller.

 

The connection between the greeting property and the value property is actually a live one. Anytime you change the greeting property, it will automatically update the label. To try this yourself, open your app in Safari with the Develop Menu enabled or FireFox with Firebug and on the JavaScript command line type:

 

SC.run(function() { HelloWorld.appController.set('greeting', 'I am changing!'); });

 

And you should see the text of the label change as well.

 

This works because of the binding you just added to the label view. A binding is like a wire that connects a property on one object to a property on another. Whenever the value of one property changes, the other one will be updated automatically. It’s one of the most central ways SproutCore keeps things in sync across your app. Bindings also help you write more maintainable code since you can often write modules independently and then hook them together at the end using bindings.

 

That’s it for this step of the tutorial. In the next step, we’ll learn more about how to use bindings and properties along with buttons to change your UI dynamically.

 

Go to Hello World Tutorial 3: Adding Buttons »

 

Comments (37)

Cleland Early said

at 7:12 am on Aug 12, 2009

When I try to complete step three, I get an error message: "FATAL ~ This generator requires a Target." I'm not sure which directory you need to be in to run this command (sc-gen controller) as documented. Wwhich directory exactly is the "root project directory (the one with the clients folder)"? I do not see a "clients" folder in any of the folders in any of the project directories I've created so far. Could you be more explicit?

gramby said

at 7:29 am on Aug 12, 2009

Assuming that you have a directory named hello_world generated from the 'sc-init hello_world' command, and that you have changed to that directory, the 'sc-gen controller HelloWorld.appController' command should work. The 'clients' directory was applicable to the previous SproutCore system. It's now called 'apps'.

gramby said

at 7:30 am on Aug 12, 2009

I updated the page to reference apps rather than clients.

Cleland Early said

at 8:38 am on Aug 12, 2009

Turns out my problem had to do with not following the naming conventions, or so it appears. I was actually trying to create a different project with a different name. It looks like the tool expects the project to be named in a certain way. If you want to create an app controller for a project called joeblow, you would need to call "sc-gen controller Joeblow.appController". If you call "sc-gen controller JoeBlow.appController", you get the message I describe. If you want the controller to be called "JoeBlow.appController," you need to name the project "joe_blow".

Pedro Luz said

at 5:10 am on Aug 26, 2009

after writing the binding the "Hello World!" sentence from the controller is not appearing :(

running firefox with firebug... and is not giving any error

why?

Pedro Luz said

at 5:13 am on Aug 26, 2009

ups... my bad :(... my mistake... it's working WEEEEEEEEEEE :D

Larry Siden said

at 8:20 pm on Oct 25, 2009

Do you remember what you did to get it to work, Pedro?

Larry Siden said

at 8:26 pm on Oct 25, 2009

Never mind! I made a dumb mistake too!

Parker Morse said

at 1:23 pm on Aug 9, 2010

So that makes two of you who found solutions and aren't telling.

Guy said

at 11:21 am on Oct 1, 2009

The main_page.js file is in a folder called 'resources' for me, not 'english.lproj'. Do I not have the latest code, or is this tutorial outdated from the newest code? If the former, how do I get the latest?

Louis Chen said

at 4:47 pm on Oct 1, 2009

You have the latest code. The tutorials are a bit outdated because SproutCore recently is under heavy development trying to reach the 1.0 milestone.

Charles Jolley said

at 3:51 pm on Oct 3, 2009

english.lproj was renamed to resources to allow non-localized assets. You have the latest code. We're working on updating these pages.

Ivo said

at 3:43 pm on Oct 3, 2009

For step 4: the first line of code should not have quotes:

valueBinding: HelloWorld.appController.greeting

Charles Jolley said

at 3:50 pm on Oct 3, 2009

Hm - yes it should have quotes. I don't know how your app would even run without them! :-)

Larry Siden said

at 8:55 pm on Oct 25, 2009

This little app generates a page that downloads 195 .js files, making a total of 200 HTTP requests that total 2.2 Meg! The Cache-Control HTTP header field on each specifies a max-age of 0 so nothing is cached. I thought SC was supposed to be fast?! What gives?

Charles Jolley said

at 10:10 pm on Oct 25, 2009

You are trying SproutCore in development mode. The files aren't minified or combined in order to make it easy to debug. Try doing a build to get the actual files you want to deploy. Try:

sc-build hello_world -rc --languages=en

to get a taste of the real output.

Juan Pinzon said

at 10:57 am on Oct 30, 2009

you can also use sc-server --mode production

Johannes Krampf said

at 2:58 pm on Oct 29, 2009

Controller/Bindings didn't work for me with Ruby 1.9.1 on ArchLinux. I tried it in Ruby 1.8.7 in a Ubuntu 9.10 VM and everything works fine now. (Both using Sproutcore 1.0.1009 and following the tutorial to the letter.)

The same happened with the Todos application - Firebug complained that Todos.tasksController was undefined, looking at HelloWorld.appController it was undefined with Ruby 1.9.1, too.

Ido Ran said

at 7:22 am on Dec 8, 2009

Hi, I've been trying to work with this tutorial and with the Todos one and I guess I'm missing something.
I have sproutecore 1.0.1037 (according to gem list)

I've create a new project with sc-init and everything works when open localhost:4020.
I've change the text in main_page.js and after refresh I see the new text.
I've create the appController which create file called app.js in controllers folder and here the problem start.
If I refresh the page (I'm using Safari on Mac) and open the Dev Console and write HelloWorld.appController I get undefined - off course after changing the label to have valueBinding and bind it to HelloWorld.appController.greeting nothing is display after refresh.

Same thing happen to me with the Todos tutorial. After adding the model Todos.Task for some reason in the Dev Console it is undefined.
I don't see that Safari download app.js (the controller). Am I missing a require or include or something like that?
How does SproutCore know which files to include in the site?

Thank you very much,
Ido.

Ido Ran said

at 7:54 am on Dec 8, 2009

I forgot to write that when I use the samples downloaded from Sproutcore repository everything works just fine. The samples_todos work and when I write in the Dev Console Todos.Task I get an object describing the model so it must be something I do, or didn't do.

Ido.

Charles Jolley said

at 8:49 am on Dec 8, 2009

Ido, where is your app.js file? It should be in apps/hello_world/controllers/app.js. If it is there and you still don't see it, try killing your sc-server and run it again.

Ido Ran said

at 10:49 am on Dec 8, 2009

Yes, the file app.js and I have killed (Control+C) the sc-server and run it again. Does it matter where I am running sc-server from within app/hello_world sub-directories?

How does SproutCore know to include the *.js files from controllers and models direcoties?

Ido Ran said

at 7:16 am on Dec 12, 2009

Hi,
After getting help from good man at #sproutcore irc room it turns out that I had to delete the tmp directory under my application directory before running sc-server.
It is a workaround but it works.

Ido.

Russell Gum said

at 10:08 pm on Dec 13, 2009

"To try this yourself, open your app in Safari with the Develop Menu enabled or FireFox with Firebug and on the JavaScript command line type:"

In Safari how do I find the JavaScript command line?

Dave said

at 12:52 pm on Dec 14, 2009

If you're on a mac, in Safari, you need to enable the Developer menu. Instructions via Google here: http://www.moodyclouds.com/2007/12/02/safari-web-developer-tools/

If you're on a PC, I'm not sure how in Safari, but in Chrome it's dead easy, you just right-click on the page and select "Inspect Element". Note that the documentation is written with examples in Safari's (somewhat superior) dev console.

Russell Gum said

at 9:07 pm on Dec 14, 2009

Thanks. I can now use the error console from the develop menu to type in and evaluate java script.

Bob Sander-Cederlof said

at 5:54 pm on Feb 13, 2010

I installed sproutcore yesterday, on MacOSX 10.5.8. In order to get HelloWorld to work with a controller, I had to change the name of app.js to appController.js. The sc-gen named it app.js, but in the text of this tutorial, it says it is named appControler.js
What is correct?

Juan Pinzon said

at 6:51 pm on Feb 15, 2010

I updated and confirmed that this tutorial works by just copying and pasting the snippets of code. There were some outdated snippets of code that might have broken the styling but in general everything worked.

Superman said

at 1:52 am on Jul 24, 2010

Hi,
I need help with this line from above tutorial.

"There are two other files inside resources: string.js which will contain all the strings necessary for localization purposes and main_page.js, which describes the main user interface for your application."

I don't have any string.js in whole project. And I follow all the steps till now in this tutorial. However project is also working fine till now. But bit confused why I don't have this file.

Amandeep Singh said

at 2:22 am on Aug 9, 2010

same here...

Ronald Hayden said

at 6:39 pm on Jul 25, 2010

As with Bob Sander-Cederlof, I couldn't get this to work until I changed the auto-generated controller from app.js to appController.js...

Parker Morse said

at 2:04 pm on Aug 9, 2010

As with several other people, this tutorial comes off the rails for me around Step 3. The file apps/hello_world/controllers/app.js is created, I copy/paste the line defining "greeting" in there, I copy-paste the binding into main_page.js as explained in Step 4. At this point, nothing shows up in Firefox. The Console shows this error:

HelloWorld.getPath("mainPage.mainPane") is undefined
[Break on this error] HelloWorld.getPath('mainPage.mainPane').append() ;

This is attributed to line 20 in main.js.

This is a Mac with 10.5.8, and Ruby 1.8.6. The browser is Firefox 3.6.6.

I tried changing the controller name from app.js to appController.js as suggested above, but that made no difference (same error). After changing the name, I did restart the server and delete the tmp/ directory, also as suggested above, and that also failed.

I appreciate Juan's going through the code and it working for him, but when it is here on my screen clearly NOT working, it would help a lot to know under what circumstances it worked for him so I could figure out what's going wrong here. Without more details the whole experience is very frustrating.

Parker Morse said

at 2:07 pm on Aug 9, 2010

I should add that I get a similar error with Safari 5.0. The error message in the console there is "TypeError: Result of expression 'HelloWorld.getPath('mainPage.mainPane')' [undefined] is not an object."

Parker Morse said

at 6:22 pm on Aug 15, 2010

Since this comment, I've marched through the tutorial again without troubles, so either I understand SproutCore better now (tip for those who get fed up with Hello World at this point: go on and do the ToDos tutorial first, then come back to this one) or it has been updated to fix the issues I was having.

For those who come up with errors indicating 'HelloWorld.getPath('mainPage.mainPane') is undefined, I've discovered that this generally indicates an error in your MainPane definition in main_page.js.

Perry Donnafield said

at 9:23 am on Aug 10, 2010

Hey Parker, I too have had the same issues. Not sure what Juan is doing but there are issues. To get this to work for me I had to put quotes around the HelloWorld.appController.greeting valueBinding in step 4. Charles Jolley mentions this above. The tutorial is incorrect at that point. If I leave off the quotes I get nothing. Oh, and you can leave off the comma at the end of the valueBinding line as well. I also deleted the tmp directory. Hope this helps.

Perry Donnafield said

at 9:28 am on Aug 10, 2010

I updated the tutorial at step 4. The valueBinding line should now be correct.

Amandeep Singh said

at 7:57 am on Aug 17, 2010

Hello Perry
I tried the tutorial again today. This time, it worked without quotes, which it didn't the previous time!!! Weird!!!

Also, I wasn't able to get "SC.run(function() { HelloWorld.appController.set('greeting', 'I am changing!'); });" working using firebug in Firefox. The string was not updated. Any ideas?

You don't have permission to comment on this page.