Skip to content

Commit b569bc4

Browse files
author
raorao
committed
creates advanced JavaScript curriculum
1 parent b429f48 commit b569bc4

10 files changed

+1221
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
goals do
2+
goal "Allow a user to create a new item."
3+
goal "Understand how to make an AJAX request when prompted by a user's action."
4+
end
5+
6+
overview do
7+
message <<-MARKDOWN
8+
JavaScript allows us to make our web page dynamic, and responsive to
9+
the actions of our users. In this lesson, we'll allow our users to create
10+
a new item for our list, and ask the server to save it to the database.
11+
12+
To do so, we're going to use JavaScript's ability to perform a task when a
13+
user has taken an action on the page. JavaScript refers to these actions as
14+
__events__. React makes it easy to listen to these events, and cause the page
15+
to change when nevessary.
16+
17+
Our code will take the following steps.
18+
19+
1. When the user loads the page, our CreationForm component will start
20+
listening for when the user submits the form at the top of the page.
21+
22+
2. When a user submits the form (by pressing enter), we will prevent the page
23+
from refreshing, which is the normal behavior for a form.
24+
25+
3. The CreationForm component will then tell ListStore to add a new item.
26+
27+
4. ListStore will make an AJAX request to our server, creating an item with the
28+
description our user just provided.
29+
30+
5. Once the request succeeds, we will update the items variable with our new item.
31+
32+
6. Finally, we will tell the components to re-render themselves!
33+
34+
We've already written the first two steps for you. Let's finish the rest!
35+
MARKDOWN
36+
end
37+
38+
39+
steps do
40+
step do
41+
message <<-MARKDOWN
42+
In the browser, try creating a new item. You should see an alert pop up with your item's value. Let's take
43+
a look at the CreationForm component to see how that works. Open up index.html in your browser, and find the
44+
component. It looks like this:
45+
MARKDOWN
46+
47+
source_code :javascript, <<-JAVASCRIPT
48+
render: function() {
49+
return (
50+
<form id="add-form" onSubmit={this.handleSubmit}>
51+
<input id='create' ref="description" type='text' placeholder='Add Something to the list!' />
52+
</form>
53+
)
54+
},
55+
56+
handleSubmit: function(event) {
57+
event.preventDefault()
58+
var description = this.refs.description.getDOMNode().value
59+
this.refs.description.getDOMNode().value = ''
60+
alert('trying to create an item with description ' + description)
61+
}
62+
JAVASCRIPT
63+
64+
message <<-MARKDOWN
65+
When the form submits, the handleSubmit function runs! This function is preventing the page from refreshing
66+
(using the preventDefault function) and using React to get the new description the user just wrote. See if you
67+
can follow the code – how does the form know to run the handleSubmit function?
68+
69+
Now, let's remove the alert, and instead tell the ListStore to add an item. Your code should look like this:
70+
MARKDOWN
71+
72+
source_code :javascript, <<-JAVASCRIPT
73+
handleSubmit: function(event) {
74+
event.preventDefault()
75+
var description = this.refs.description.getDOMNode().value
76+
this.refs.description.getDOMNode().value = ''
77+
ListStore.addItem(description)
78+
}
79+
JAVASCRIPT
80+
end
81+
end
82+
83+
steps do
84+
step do
85+
message <<-MARKDOWN
86+
Now, let's write the logic for the addItem function. We're going to ask the server to save
87+
this item into the database. Open up store.js, and add the following code to the addItem
88+
function. Replace 'YOUR-LIST-NAME-HERE' with your list's name.
89+
MARKDOWN
90+
91+
source_code :javascript, <<-JAVASCRIPT
92+
addItem: function(itemDescription) {
93+
var creationRequest = $.ajax({
94+
type: 'POST',
95+
url: "http://listalous.herokuapp.com/lists/YOUR-LIST-NAME-HERE/items",
96+
data: { description: itemDescription, completed: false }
97+
})
98+
},
99+
JAVASCRIPT
100+
101+
message <<-MARKDOWN
102+
Try creating an item again. After you submit the form, look at the network tab. A
103+
new request should have occurred to http://listalous.herokuapp.com/ !
104+
MARKDOWN
105+
end
106+
107+
step do
108+
message <<-MARKDOWN
109+
Finally, we need to tell the components to re-render themselves. After the creationRequest,
110+
add the following code:
111+
MARKDOWN
112+
113+
source_code :javascript, <<-JAVASCRIPT
114+
creationRequest.done(function(itemDataFromServer) {
115+
items.push(itemDataFromServer)
116+
notifyComponents()
117+
})
118+
JAVASCRIPT
119+
120+
message <<-MARKDOWN
121+
Try creating an item one more time. Once you hit enter, a new item should appear
122+
on the page! If not, flag an instructor down to help you debug the problem.
123+
MARKDOWN
124+
end
125+
end
126+
127+
explanation do
128+
129+
message "Here's what the bottom of store.js should now look like:"
130+
131+
source_code :javascript, <<-JAVASCRIPT
132+
ListStore = {
133+
134+
getItems: function() {
135+
return items
136+
},
137+
138+
loadItems: function() {
139+
var loadRequest = $.ajax({
140+
type: 'GET',
141+
url: "https://listalous.herokuapp.com/lists/YOUR-LIST-NAME-HERE/"
142+
})
143+
144+
loadRequest.done(function(dataFromServer) {
145+
items = dataFromServer.items
146+
notifyComponents()
147+
})
148+
},
149+
150+
addItem: function(itemDescription) {
151+
var creationRequest = $.ajax({
152+
type: 'POST',
153+
url: "http://listalous.herokuapp.com/lists/YOUR-LIST-NAME-HERE/items",
154+
data: { description: itemDescription, completed: false }
155+
})
156+
157+
creationRequest.done(function(itemDataFromServer) {
158+
items.push(itemDataFromServer)
159+
notifyComponents()
160+
})
161+
},
162+
toggleCompleteness: function(itemId) {}
163+
}
164+
JAVASCRIPT
165+
166+
message <<-MARKDOWN
167+
168+
### The AJAX process
169+
170+
You've just done something that many JavaScript developers do daily: Use JavaScript
171+
to make a request to a server, and then update the page with the data with which
172+
the server responds. This abstract process is repeated over and over again:
173+
174+
1. Listen for a user action on the page.
175+
2. Parse out the information the user is submitting.
176+
3. Prevent the default action from occuring, if necessary.
177+
4. Make a request to the server using AJAX.
178+
5. When the request succeeds, parse the data the server sends back.
179+
6. Update the page with the newly received data.
180+
181+
This process is the basis of most modern web pages!
182+
MARKDOWN
183+
end
184+
185+
next_step "marking_an_item_as_complete"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
goals do
2+
goal "Understand how modern web developers organize their code."
3+
goal "Familiarize with Stores, JSX, and other features of a React application."
4+
end
5+
6+
overview do
7+
message <<-MARKDOWN
8+
When the web was in its infancy, JavaScript was often an afterthought. Web developers
9+
were mostly concerned writing complex servers, and thought of JavaScript as a language to
10+
simply make things move on their user's pages. Consequently, their JavaScript code
11+
was often unorganized, untested, and hard to maintain.
12+
13+
But as browsers became more advanced, JavaScript was suddenly asked to do much more – web
14+
developers used JavaScript for complex animations, making requests to servers, even doing
15+
complex calculations in the browser! The old approach of writing all your code in one place,
16+
with all the logic jumbled together, quickly became untenable. In response to that, the
17+
JavaScript community has started developing patterns to help themselves organize their code,
18+
making it more readable. Most of these patterns separate code into two buckets:
19+
20+
* __Views (or Components, or View Controllers)__ are in charge or rendering HTML elements, and
21+
listening for user's actions like clicks and form submissions.
22+
* __Models (or Stores)__ are responsible for the logic of your JavaScript application.
23+
24+
There are many JavaScript libraries and frameworks that implement this structure, including
25+
[AngularJS](https://angularjs.org/), [Ember.js](http://emberjs.com/), and [Backbone.js](http://backbonejs.org/).
26+
They each have their own strengths and weaknesses. and we wouldn't presume to tell you
27+
which one is "better." As you continue learning, you'll form your own opinions!
28+
29+
For this tutorial, we'll be using [React](http://facebook.github.io/react/), a rendering library written by Facebook that has
30+
grown in popularity over the last few years. To use React, you write your HTML as a series of __components__
31+
in a language called __JSX__. Don't worry, JSX looks a lot like HTML! These components handle
32+
the rendering of your HTML elements, as well as listen for user actions.
33+
34+
You'll be using React to make your view objects, and we'll use a simple JavaScript object as a model. We've
35+
already built a lot of this structure for you! Let's walk through the code together.
36+
MARKDOWN
37+
end
38+
39+
40+
41+
42+
steps do
43+
step do
44+
message <<-MARKDOWN
45+
Open up store.js in your text editor. There, you should see a ListStore object defined like this:
46+
MARKDOWN
47+
48+
source_code :javascript, <<-JAVASCRIPT
49+
ListStore = {
50+
getItems: function() {
51+
return items
52+
},
53+
loadItems: function() {},
54+
addItem: function(itemDescription) {},
55+
toggleCompleteness: function(itemId) {}
56+
}
57+
JAVASCRIPT
58+
59+
message <<-MARKDOWN
60+
This is where all the logic of our application will be performed! Whenever we need to execute a calcuation, or
61+
make an AJAX request, our program will call a function on the ListStore object. For instance, when we want to load
62+
all items from our server, you would write a line of code like this:
63+
MARKDOWN
64+
65+
source_code :javascript, <<-JAVASCRIPT
66+
ListStore.loadItems()
67+
JAVASCRIPT
68+
69+
message <<-MARKDOWN
70+
In future lessons, we'll be writing the logic to make these functions work! Whenever the store changes – when an item
71+
is added or marked as completed, for example – we'll use the notifyComponents function to update the user's page.
72+
MARKDOWN
73+
end
74+
75+
step do
76+
77+
message <<-MARKDOWN
78+
Now that we've looked at the store, let's take a look at our components. Open index.html, and find the Item component. It should
79+
look like this:
80+
MARKDOWN
81+
82+
source_code :javascript, <<-JAVASCRIPT
83+
var Item = React.createClass({
84+
render: function() {
85+
var itemClass = this.props.completed ? 'item completed' : 'item'
86+
return (
87+
<li className={itemClass}>
88+
<span className='complete-button'>{'\\u2714'}</span>
89+
<div className='description'>{this.props.description}</div>
90+
<span className='delete-button'>{'\\u2718'}</span>
91+
</li>
92+
)
93+
},
94+
})
95+
JAVASCRIPT
96+
97+
message <<-MARKDOWN
98+
This is a React component. It is responsible for rendering the HTML for our list's items! Every React component has
99+
to have a render function, which are written in a language called JSX. It looks a like HTML, except you can write it
100+
alongside your JavaScript code. Here's the HTML this component renders:
101+
MARKDOWN
102+
103+
source_code :HTML, <<-HTML
104+
<li class='item completed'>
105+
<span class='complete-button'>&#10004;</span>
106+
<div class='description'>A gallon of milk.</div>
107+
<span class='delete-button'>&#10008;</span>
108+
</li>
109+
HTML
110+
111+
message <<-MARKDOWN
112+
Take a look at the other components on the page. What do you think List component does, and how does it know to render
113+
items? How about the CreationForm component?
114+
MARKDOWN
115+
end
116+
117+
step do
118+
message <<-MARKDOWN
119+
Now you know what a React component looks like, but how does it work? Well, components can have __state__.
120+
Whenever a component's state changes, it re-renders itself to the page! State can change in a handful
121+
of ways. We've already written a function to make List's state change whenever the notifyComponents
122+
function is called. This will be helpful later on!
123+
124+
Components with state usually also implement a getInitialState function that tells the component what
125+
to render immediately after the page loads. Our List component has one that looks like this:
126+
MARKDOWN
127+
128+
source_code :javascript, <<-JAVASCRIPT
129+
getInitialState: function() {
130+
return (
131+
{items: [
132+
{description: 'a gallon of milk', completed: true, id: 1},
133+
{description: 'a stick of butter', completed: false, id: 2}
134+
]}
135+
)
136+
},
137+
JAVASCRIPT
138+
139+
message <<-MARKDOWN
140+
Does that data look familiar? It's the default items that our list renders! Try changing these values.
141+
Refresh your browser, and see what's changed!
142+
143+
Before we move on, let's remove the default items altogether. Not everyone wants a gallon of milk!
144+
Your code should look like this:
145+
MARKDOWN
146+
147+
source_code :javascript, <<-JAVASCRIPT
148+
getInitialState: function() {
149+
return (
150+
{items: []}
151+
)
152+
},
153+
JAVASCRIPT
154+
end
155+
end
156+
explanation do
157+
158+
message <<-MARKDOWN
159+
160+
### Getting Comfortable with React.
161+
162+
You've just looked at your first React application! There are a lot of moving parts, we know.
163+
Don't worry if you don't understand how everything works just yet – as you keep playing with it,
164+
it will become much clearer. Big picture, our web application has two parts:
165+
166+
* A ListStore, which is responsible for fetching data from the server using AJAX, and keeps
167+
track of all the items on our list. Whenever a new item has been added or updated, it will notify
168+
all the components that it has changed.
169+
170+
* A series of components that render our list as HTML. The List component updates whenever
171+
the ListStore changes, and it renders a series of Item components. The CreationForm component
172+
will be responsible for creating new items!
173+
174+
Next, we'll write our first store function to load items when the user visits the page!
175+
MARKDOWN
176+
end
177+
178+
179+
next_step 'loading_items'

0 commit comments

Comments
 (0)