Next talk, we had some slides about EmberJS. Some of you might have seen this last talk.
What was it about? It was more like...
Advanced EmberJS and it fell on its face.
And now we're getting more like into the core concept of EmberJS and some light coding sessions.
Yeah. And I'm really excited.
Okay, so how many people were here for my talk last month about Advanced Ember?
Okay, how many people didn't know anything I was talking about?
Okay, so I'm going to do a general introduction to Ember,
and I'm going to program something in front of you guys.
And if you have any questions at all during...
Well, during it, just ask. I just want this to be like a learning and informative session.
How many people have used Ember before?
Okay, great. So, nobody.
So, but...
Okay, somebody touched it one time.
So tonight I will take your Ember virginity.
So, I was thinking that I could make just a basic...
I mean, who here is seen to do MVC?
Okay, so a few people. So, how I have like half an hour, 40 minutes, something like that?
Yeah, so I was thinking that just making it to do is application.
Does anybody have an idea of what they would want to see?
I can program something else maybe that... No?
What? Bacon?
I don't know how to program bacon.
Do Reddit.
Okay, I'll do Reddit.
So, we will make like a basic social news site now with Ember.
We'll have like a submission, like a page where you list the submissions.
You can add like a new link, and then maybe if we have time you can comment on it.
Okay?
So, here we are in LovelyVim.
I have set up a basic, just HTML file.
It just loads jQuery, which is a dependency, handlebars, which is a dependency, and Ember.
So, jQuery, Ember depends on handlebars and jQuery,
and then I have my app.js file, which I'll just write all the code in there.
And here's our basic template for the application.
So, if we go to Chrome, the application here is running.
So, Ember is MVC.
You have model views and controllers, and you also have templates which are...
Well, how you render the view, and you have routes.
So, each page, like if you were to try to map what you do in a web application or something to Ember,
you have pages and those are routes which are accessible via the URL.
There's the Ember router, which translates a URL into a state of your application,
and that state of your application is a model, a view, and a template.
So, for example, if I go to slash, that's the no route, basically.
It knows, okay, I just go in to load the application.
And this is the template for the application here.
So, the first thing we'll do is make a list of all our submissions.
And that will just happen inside application view.
Yeah?
Yeah, okay, so...
No, no, no, okay, so app.js is nothing, actually.
It just create an app global variable.
And so, when Ember boots, if you happen to have script with this type here,
it will then compile that down into a handlebars template.
So, we'll start out just by listing some stuff.
So, we'll create...
Ember does a lot of code generation for you.
So, for example, I haven't actually written any JavaScript to put this on the page.
I just created the application.
So, under the covers, it's actually creating an application view,
an application controller, and...
Well, no model, but it's creating these files for you.
So, like, now I will create a controller to hold all of our data.
So, I'll just create an array of stories.
And sorry if I make mistakes with JavaScript, I haven't used it for a long time.
I can't use copyscript now all the time.
So, Ember is basically composed of Ember objects.
It's like the root object for every type of object inside Ember,
and it sets up the observers and all these things like that.
So, you can...
Ember gives you beta bindings.
How many people have used, like, knockout or anything like that?
Yeah, okay, so you can define properties on Ember objects
and then include them in the template, and Ember will update the template.
So, for example, if I have, say, name foo, okay,
I can go back to my template and write name.
Now, if object's name happens to change, the view will be updated for you.
You don't have to worry about that.
So, let's say it's declarative data bindings.
So, I will create some objects just like...
So, we'll have a title, say...
Thank you.
And we'll just create, like...
Just a few of these.
Now I have this object, this array of objects.
So, now, in order to put it on the page,
I need to create a controller to hold this app,
like, to hold this data and pass it off to a view.
So, we haven't actually created any controllers yet.
It's all happened for us automatically.
So, I can create something like app.applicationController,
ember.controller, extend.
And this...
So, ember also includes a classical inheritance implementation
on top of prototypical inheritance.
So, extend is like inherits in languages.
It also includes a module system so you have multiple inheritance.
So, let's just...
We'll just leave this how it is.
So, I mentioned that there's also a router,
and that's the thing that's managing the state of your application.
So, it's where you set up what properties the controller should have,
what data it's connected to,
where it should render on the page, and all this sort of stuff.
So, I can create a file or an object called applicationRoute.
Which, again, inherits from ember.route,
and then you can customize this, well, to do whatever you need to.
So, the main hook is the model hook,
where you define what data is associated with this particular state.
So, I can say model is a function, right?
No, that's not right. There we go.
And I could just take this
and just do, say, return stories.
Okay.
Now, at this point, we're still not going to have anything on the page.
We need to actually, well, loop over this data, basically.
So, what we can say is each in controller,
or no, we'll just say stories, for example,
and then...
Okay.
Handlebars?
Yeah, handlebars, yeah.
So, we have the model.
Okay.
No.
No, nothing.
Doo, doo, doo, doo, doo, doo, doo, doo.
ApplicationRoute, model, application, controller.
Oh.
Right.
Let's save.
So, there's two different...
There's, like, three different controllers or controller types.
There's just a controller, which is, like, the abstract basic type.
There's an object controller and an array controller.
All the controllers are proxies to the underlying object.
So, in this case, since we have an array, we'll use an array controller.
And do we have anything yet?
No.
Not niched.
Shries.
No, I can just return it here.
No, it's var right here.
Yeah.
Yeah, and then return this array.
Oh, that's right.
It should be a controller.
So, yeah.
So, because what's actually happening under the covers is it's saying,
set the content, like, the underlying object, this controller proxies,
to this array, and you can access it via the controller.
So, conversely, like, we could change...
There's another hook we could use.
It's called setupController.
And that takes a controller and a model.
And we could say...
I mean, we can change this to be just, like, just a controller.
And then we can say controller.setStories.
Stories.
And then we can change this to stories.
And then everything's fine.
So...
So, that was just a quick example of how you can set, like, more properties.
Here, just use the controller, because what you can do is actually mix in...
Ember already provides some functionality for you in the controller,
so you can mix in things like sorting.
So, for example, when you say each controller that will take into account
everything that's happening inside the controller,
and the controller might do things like sorting or whatever.
So, now we have our...
What?
Yeah.
You're right.
Now this has to change back to arrayController.
So, now we can, like, add some more submissions.
So, basically, when you...
Like, if you were to divide up your application
into, like, little bits of functionality, your, like, discrete chunks,
that's gonna be, like, a model, a view, and a controller.
So, what we're gonna do now is just create a form
where you can submit a new, well, a new submission
that will have a URL and a title, okay?
Now, in order to do that, we have to give...
We have to create a JavaScript object that represents this concept, right?
So, we can create...
We could create a submission, like, object,
or it could just use a controller itself, right?
So, we can create a controller.
We'll just call it submissionController.
I'll just say ember.controller.extend,
and we can give this some, like, default properties.
So, we could say title is...
Right.
Yeah, I know.
JavaScript.
I don't know how you can ever write JavaScript again
after you've written CoffeeScript.
Okay.
So, now we need to, like, actually create a form
where we represent this data.
So, then to demonstrate some, like, other parts of the framework,
I'll break this up into, like, a partial, basically.
How many people have used Rails at all?
We're familiar with, like, I have this template,
and I write it somewhere, and now I just want to use it.
Yeah, okay.
So, we'll, like, do it as a discrete thing.
So, we can create a new template for it.
We'll just call it textX handlebars
and say template name submission.
Oops.
And we'll just make a form,
and then we'll need two input boxes
and a button to submit the form.
So, writing forms in Ember is kind of different
than what you would usually expect.
So, what you actually do is use a view
that can handle text input and the binding way to that.
So, what we say is view ember.textfield.
Right, and we'll just say title,
and then we'll make another one that's a URL.
Okay, ember.textfield and the form,
and now we need to, like, this is now a basic template,
but it's not connected to the application in any way.
So, in order to connect it, what we need to do
is tell it to render inside another template.
So, we can say render submission.
Oops.
Well, it is Yehuda.
So, what this is going to do is going to look up this template
name submission, which we've defined here in this block
of handlebars and passed in this name.
So, it will look up submission and then a submission controller
and then dump that into the view.
So, we have our submission controller here,
and now things should work, and we have our input boxes here.
Now, at this point, we can type whatever we want into these boxes,
but they're not actually connected to anything.
So, now what we have to do is connect what's displayed in the DOM
versus the state of our application inside JavaScript.
So, yes.
Is this a render submission, is this handlebars,
or is it a combination of ember and...
Yeah, it's a handlebars helper added by ember.
So, ember adds, like, a lot of helpers as well.
We have render, view, which we've seen here,
and then, like, link to, do the right links for your application,
and, like, a bunch of other stuff.
So, just to demonstrate, like, what's going on here,
there's two different parts of the app,
two different, like, subsections on the screen,
each controlled by a different controller.
So, if I say...
We'll just put some, like, debugging in this thing here, right?
And then we can just say...
Don't use this in production code, but...
So, we can see that we have, like, a div, whatever,
and this part is controlled by a different controller,
and this part is controlled by a different controller.
So, now we need to connect them, right?
So, you do this by declaring a binding
between one part of the application
to another part of the application,
and you can pass that in in handlebars.
So, you can say value binding equals, in this case, title,
and then, down here, URL.
Now, this means the title.
Title is also defined on the submissions controller here.
So, when I type in that box,
it's going to set the title property on the controller or the URL, right?
So...
Okay, nothing is blown up, right?
But, as you can see, now we have the default,
the values we specified in the controller here.
So, just so we can see that it's working,
we can also just put something here,
and we'll say title, URL, right?
There's nothing here, but I can type, right, and it changes.
You don't have to do anything.
So, now we have, like, our basic data binding,
and it's the same thing up here,
just that we haven't interacted with that data yet.
So, the next thing we have to do is create the button, all right?
And we do that just by writing, well, a button,
and we'll say...
Right?
Then, we'll declare, like, using another Ember handlebars helper,
and that's the action helper.
So, that's gonna say, we'll say action, and then post, okay?
So, this is gonna send a, like, a message up the chain.
So, if we go back to the application,
we have our submission controller here,
which is then part of the, well, sub-rendered by the application.
So, you have submission inside application,
and then the router composes the whole thing.
So, you have a tree, essentially, right?
And then, that's gonna, when you click on this button,
it's gonna send this post message all the way up the tree.
So, to implement that, you just implement a post method
on whatever object you want.
No, it's just an act, like, it's just a method name, essentially.
Yeah.
Yeah, I mean, I could call this foobar or whatever,
and define foobar, it makes no difference, right?
So, then...
So, there's actually a few different ways to do this,
but I'll do this, like, the Ember way, basically.
So, the Ember way is to implement action handling
on the route object,
because the route object defines, like, a state of your application,
and you may want to handle actions differently,
depending on what state of the application you're in,
versus if you defined it on the controller,
it would be the same everywhere.
So, now we can define application route,
which Ember defined for us automatically.
Oh, it's already there.
Oops.
My bad.
So, make an events property,
and then we can...
Fucking JavaScript.
And then we can define post,
which is just...
a function.
Yes, a function.
Yeah.
And then, classic JavaScript debugging,
we can say...
I know everybody's done this before, don't be afraid.
Yeah, thank you.
I still do it, too.
It never fails.
Okay, so, at this point, I could post that shit.
Oh, nothing handled the event in post.
Oh, it has to be events, my bad.
So, yeah, so you get the error saying, like,
that nothing handled that event, doesn't know what to do.
So, we can reload the page, and we can post it again,
and now we're in the...
like, where we want to be.
So...
Yeah, it's just, basically, they're just mapping
some method names somewhere.
So, now...
I could.
You could define it in the controller.
Just, for this case, we'll just put it here.
Yeah, because you could...
So, for example, it's on the application route,
which is the highest part of the tree.
So, if you had, like, you know, nodes lower down in the tree,
you could define it there to customize it, right?
So, I mean, application route is the stuff you would put
global things for the whole application.
Like, for example, log out, or something like that.
So, now the question is, how do we actually get
the data that they type into the form?
And this is done by accessing...
accessing the controller, so the submission controller.
This might actually be broken.
So, I think...
It's just...
I think that will do something.
Okay, yeah.
So, we can say...
Yeah, so, controller four is just a way to look up a controller,
because you don't actually...
because Ember is managing the instances for you.
So, you can't just say application.controller.create.
You have to actually look up the instance it's using in the application.
So, then you can say, okay, let's get the properties.
So, we could just say...
URL, and just to see if it's working,
we will now, again, alert some stuff.
Right?
Okay, so now the question is, we have the data, now what do we do with it?
Right?
I mean...
The question is, we want to just put this stuff on the page, right?
We don't have to worry...
We don't want to worry about anything else.
So, I mean, we have this array of stories,
but we don't have access to this particular thing, right?
But we do have access to the controller managing those stories.
So, we can use that.
So, we could say, just put this here, and we'll now create a new object.
We'll say, new story...
And we'll say, title, URL, URL.
Oops.
And now...
What?
No, it didn't speak German yet.
I don't blame it, German's hard.
So then, we know how to access the submission controller,
so we can use the same logic, the same method to access the application controller
and look up the property.
So, we could say, this.controller for application, push object, story.
Oops.
So, push object is a method defined on Ember array,
which then, of course, the array controller is array proxy,
which proxies that method to whatever it is below it.
So...
And everything is there, right?
So, great.
But now, I mean, I want to actually go to these links.
We need to actually make these things do something, right?
So, what you can do now is just...
Index.
So, we have...
Well, we'll make this...
So, here's some cool stuff, actually.
We can say, else...
And then, in here, we can put, like, our list of things.
So, we can say a.ref equals...
Now, I'm going to do something that's broken to show you something.
URL.
Because this is what you would think would work, right?
That's the problem.
Then, we'll just put the title in there.
Right.
Now, that should be okay.
Okay.
So, they look like links.
They sure as hell don't act like links.
Look at that.
That's not a link.
That's a metamorph.
So, if you...
Well, okay.
If we look at the DOM here,
and just go to one of these links...
We have this horrible clusterfuck of markup.
Not really.
Because what it does is, whenever you write double clip braces,
it wraps whatever you...
Wraps that thing, that expression in a metamorph,
which is essentially just two script tags.
And each...
Because then, each time you do that,
it declares, like, an ID, like a binding link.
So, it knows that when this property has changed,
I need to go to this exact position in the DOM
and replace the HTML with whatever this is, right?
So, that's a wonderful place, but we can't go there.
So, because Ember uses bound by default, right?
You actually have to tell it explicitly that
I don't want this data to change.
And you can do that by specifying unbound.
And now, our links...
Well, of course, no internet, but then they work, right?
So, maybe now we want to have, like, some comments or something, right?
Like, we have, like, your typical, like, listing page,
and now we want to have an individual item page.
Now, this happens by defining another state of the application.
So, at the moment, we have one state, the listing,
and we'll have a new state for the individual item view.
One question.
Does it still work when you just hit post that shit?
Mm-hmm.
Oh, okay. Cool.
Yeah.
Luckily, for us, post that shit always works.
Anybody else have any questions so far?
No? Okay.
So, if we go back to our app.js file,
we can define a new route.
So, we'll put another link here.
We'll just say,
br...
Ah.
Now, how do we express this?
We say, okay, I want to go to a new page of my application.
So, this happens with the link to helper, obviously.
So, we'd say something here, like,
go to which state of the application.
So, we'd say, I don't know, submission.
And you have to pass it some context, right?
Because how does it know which submission you want to go to?
So, you just say this, right?
And we'll just say, comments.
Right.
Now, we can load this page, and it's going to blow up.
Because no route defined.
It doesn't know how to get to the state, right?
So, it's actually easier to just follow the errors, essentially.
Like, we don't have tests, but we have errors.
So, just make the errors go away,
and the application will work.
So, we do that...
We can fix this by defining a route, basically.
So, we can say, app.router.map.
This takes a function.
And we can say, resource...
Stupid.
Submission.
Yeah.
So, now, if I remember correctly, it doesn't...
Okay.
Now, more objects were passed than there were dynamic segments.
What the hell does that even mean?
Because, so, every time you create a link,
you're creating a representation of some state, right?
Like, I could copy this link and give it to somebody else, right?
They should be able to go to the same part of the application.
And it's saying, it basically can't...
I don't know how to generate a URL, given what you told me.
So, the first thing you actually have to do is
state that a route is dynamic.
And do that by passing in the path.
So, we'll say, path...
submissions.
And we'll just say...
title.
Whatever.
Makes no difference.
Right, so, at this point, if we're on a real web server,
we could go to, say, submission slash foo, right?
And load up the right submission.
Okay.
The route object object was not found.
Oh, Lord.
Okay.
Yeah, and it should have a pound in front,
and, like, basically everything is wrong.
Hey, look at that, right?
But that's, like, one weird thing.
Like, you have undefined error object object,
and it's about handlebars.
Like, yeah, you can go crazy.
So, you can click this, and, like,
look, we have this, like, wonderful URL here, right?
So, by default, it uses hash bangs,
but you can tell the router to use HTML5 history.
So, now what you have to do is look up...
you have to tell it how to serialize this object.
Now, how do I do this?
I don't quite remember.
I haven't done this manually for a long time,
because if you use Ember data with models with IDs,
it all happens for you magically, essentially.
So, there needs to be a serialized method on...
Okay, so first, like, what we have to do here
is create a submission route that knows how to serialize
and deserialize its state.
So, we'll put it down here.
Now, this is the moment where I wish I had internet,
because I can't remember the names of these methods
off the top of my head.
Oh, great.
I don't have a Cat5 port.
It's okay.
I think I can remember.
I believe it's...
Oh, great.
Ha-ha.
Oh.
I only have one port. It's for the display.
Chata. Okay.
Ah, heckler!
I believe it's called serialize,
which takes an object, a JavaScript function.
And then, basically, what you do in this case
is just define, like, what the properties would be.
So, in this case, we have, like, a route has a title.
We just return an object that has a title property.
So, say return title object dot get title.
I hope this is right.
Unexpected token.
Yeah, yep. Okay, great. Yes.
Okay.
Oh, okay. Let's go back to the beginning.
Okay, so now you, like...
Yeah, now we can see hh.js, right?
So...
Now we need to define...
Well, actually, we don't need to do it.
Because, like, when we're inside the application,
it already knows what data we want because we passed it in.
However, if you were to open up a URL and type it in,
you have to write that code as well.
But we don't need to do that right now.
So, because we passed it in right here.
So now we can define our...
We can't call it submission
because we already used submission here.
We'll just call it comments.
And we'll change this to comments.
And we will change this to comments.
And we'll just change this to comments.
And now we can create a new template for this route,
also called comments, of course.
The data template name, comments...
And now we'll put, like, our name here.
Just say title, then comments.
So now if I click on one of these comments links,
everything should go away.
Or something at least should happen.
Did I? What did you say?
That's comments.
No, comments here.
Oh, yeah, comments route.
Something is important.
No.
Oh, is it comments?
No, that should be okay.
Links here.
So welcome to the fun role of debugging Ember.
It goes in here.
Render, render, render.
X...
Comments is there.
Script type.
X handlebar is the template name.
Everything should be there.
Where?
Yeah, but that shouldn't be...
That should just raise, well, output nothing.
That's weird.
Motherfucker.
Yeah, we were on the...
Well...
Huh?
Yeah, it doesn't show when you hover over it,
but it's there in the markup.
But it's like I can't find this template name.
Sorry.
Well, inside this method,
which by default just renders the matching template
based on the name.
So comments route would render the comments template.
Oh, I know why.
There's no outlet.
Oh, okay, yeah, I totally forgot about that.
So it doesn't actually even know where to put this thing, right?
It's just...
I don't know.
You can define other parts of the application
by declaring outlets.
So we can write...
Which just basically means other parts of the application can go here.
And then, right, here's our thing.
So now we can list off comments, right?
And we can do essentially the same thing.
We can just take this here, right?
And we'll just dump it in here.
And we'll change this to comments and just say...
Oops, we need the UL.
And we'll just say text, right?
And now we can say here, no comments yet.
Now...
Astute observers will note there's no comments yet.
And there's an error.
Yeah.
And it's probably handlebars...
Yeah, okay.
Okay, let's go back to the beginning.
Now we can go to our comments.
And there's no comments yet.
So we can do essentially the same thing to implement commenting again.
So we can make a new controller and say app.commentController.
Actually, no, we don't even need that.
We just say app.commentsController, ember.objectController, extend.
And then we'll just define a text property.
Oh, yeah, okay.
So we can just take this and just dump it in here.
Oops, we'll just dump it.
That will teach me to forget copying the end of line character.
Right.
And now we can say view.ember.textArea value binding text.
Right.
So you can see that ember has actually reconstructed the state of our application based on the URL.
I mean, we were here at this comments one and...
What's that?
I think you know what you're doing, really.
So now we can just dump this post method somewhere.
So like I mentioned earlier that you should put it on the route.
But for example, we'll just put it on the controller here because we can.
So we'll say post is a function.
And we'll say var comments ember.object.create text this.getText.
We'll create an array to hold all these comments on the individual submission itself.
And then we'll say this.
This actually should be a ember.
Yeah, that looks about right.
Yeah.
Line 20.
And then...
Oh, UL and every time.
Yeah.
Problem solved.
Oh, that's right.
Yes.
So what I would like to do is say like, but no, we can't do that.
Let's just say if this.get comments do that.
Right.
So now what we want to do is clear the text area actually every time.
So we'll say this.set text null.
Right.
So we will delete this line.
And we can just say placeholder.
And now we have HTML5 placeholder thing.
We can type our thing and we can syntax error or something stupid.
Oh, no, literally nothing's going wrong besides everything.