AngularJS MTV Meetup: AngularJS + Yeoman (2012-10-9)


Uploaded by angularjs on 16.10.2012

Transcript:

BRAD GREEN: Was that the hi sign?

All right.
Hey, everybody.
Welcome.
Thanks for coming.
Some of you I've seen time and time again, so I'm
glad you've come back.
And for the new folks, welcome.
We're really glad to have you.
So we're going to do a couple things tonight.
I'm going to start off with an intro to Angular talk for
those of you who are new.
And we're going to have a couple of presentations and
show you some variety tonight.
We will have time between these sessions and at the end
to answer questions.
We really do want to get time for you to
ask specific questions.
So we're excited to come and ask those too.
The folks you can ask questions of are Mishko all
the way in the back.
Hello, raise your hand, Mishko.
Brian, here in the front.
Brian will be giving a talk.
Igor in the back, and then Voita down here.
So we're spread throughout the room, so you can share our
hands and kick us if you need to, whatever needs to happen.
So I saw a couple folks who are new.
This is for you.
And the rest of you can feel free to zone out or take a nap
or whatever you need to do.
So I want to just do a couple things in this talk and give
you the briefest taste of what Angular is about, and maybe a
little bit about why we did this.
So we did some web programming, most of us, and
we found out that it was hard.
Anyone else have that experience?
Yes, a couple.
Some people think it's easy.
Yes?
No.
OK.
I just didn't see the hands.
And in not only just being complex, which makes it hard.
It's not very fun.
I don't know.
So I started early in development.
And when I first wrote my first BASIC application, it
was something like line 10 print Hi there, 20 go to 10.
And I was blow away that it did what I said.
It was very fun.
And doing stuff in BASIC was really fun, but you couldn't
really do too much.
And the web lets us do a lot more, but it's way harder.
It's way complex compared to that first experience I had
writing some Apple II programs.
So we think it could be different.
And one of the ways that we're attempting to make this
simpler is by introducing some structure.
So the way we talk about Angular is it's a way to add
structure to your apps, and it provides support in terms of a
JavaScript library that provides this framework.
Now the structure we've chosen to support is something called
MVC, or model view controller.
Who's heard of MVC?
A couple of us?
A lot of us.
OK.
So the idea behind MVC is that we separate our code into a
couple of different responsibilities.
One called a model, or the data, in our application; one
for the view, or what the user sees, the UI; and then
something that controls how the UI reacts and how the data
flows through, and that's we call the controller.
So in an Angular app, the model we use
simple JavaScript objects.
And the data resides in those objects for your application.
And usually you'll get that data from the server.
You'll have some kind of way to communicate, and we've got
support for that.
But it's just some JavaScript objects, nothing
special about them.
We create our views out of plain HTML.
Hey, what an idea.
So instead of having some other templating language to
create what the user sees-- and usually, templates have
been rendered on the server-- in Angular, everything runs in
the client.
Everything is client-side.
We just talk to the server to get the data that the
application needs.
And here, we can just build our UI out of HTML plus a
little bit of some special stuff, that we allow you to
extend the syntax of HTML.
And we'll talk just a little bit more about that.
And then lastly, this controller is JavaScript.
You will write the logic, and this is sort of the piece that
explains or says how are the models mapped into our UI.
We do some of that in the HTML itself, and
we'll see some of that.
But the controllers also control the flow between the
UI and your model, and they say what happens.
And this is not the full application.
But basically, if I've got a JavaScript object called
files, with foo, bar, and baz in it; and I set up a view, a
piece of HTML that contains a div with some special Angular
bits-- and we'll talk about those in a minute, we call
them directives--
where I want to repeat through every file in files; and then
in my controller, I tell it how to map those files in.
Then I can have my app display something like
foo, bar, and baz.
So another way what that we've decided we would like to
simplify web application programming is in
dealing with the DOM.
This ends up being one of the places where you spend
most of your time.
And to us, it looked like boilerplate, something that
could be eliminated.
Where usually you set up a way to find an element on the
screen in your HTML that you want to talk to.
Maybe you'll set an ID on it.
And you'll get a handle to it through
some sort of CSS selector.
And then you'll want to modify it.
You'll also want to listen for events from the user.
You'll set up callbacks to tell you, a user clicked on
this, or they move the mouse, or whatever you
wanted to find out.
This ends up being a huge amount of your code in your
application.
And we've got some structure that allows you to replace
that again with some simplifying concepts.
We call them data binding and directives.
And I'll talk a little bit about them.
So data binding allows me to set up my model and my view in
the same way that we would use a spreadsheet, where I've got
various cells, and if I update one cell, I can refer to it
from another cell, and say that whenever this updates, we
should update this other cell.
This is how data binding works, is I'll set up my model
with the data that I want, and I'll map into my UI.
I've got an example here where--
and this is actually a full piece of code you could run--
where I've got a placeholder for your name, where I label
it "enter your name here." And you'll notice that in line 10,
where we say, "hello, your name," I've got curly braces
around that "your name" text.
Now what this means is that, for Angular it means I want to
insert some text here from a model element.
And in this very simple example, we're
setting up the model.
Notice on line eight, I've set ng-model, and I've set it
equal to some text called "your name." Now what this
does is it tells Angular that I'd like to make sure that
whenever somebody changes the variable called "your name,"
it updates anywhere in the app that I'm using it.
So the effect of this is that for this text input that I've
specified on line 8, if I type anything into it, the H1,
where it says, "hello, your name," will just update with
whatever the text is.
And I can demo that.

Where if I type in the text here, if I type
Brad, it just updates.
Any time I change it, it updates like that.

So the other bit of this is that we've already seen some
directives.
On that first example, where I said, ng-repeat equals
something, this is an example of us extending HTML syntax.
And these are what we call directives.
Now, the directives allow us to do much more.
There are a number of directives that come with
Angular out of the box.
But we also allow you to write whatever directives you want.
So for example, if I wanted to build a date picker, or I
wanted to use some functionality that I've
already used in building a date picker, like the one that
we see on the right there, normally what I would do is I
would build some complex set of divs and spans that
represents the structure for my date picker.
And I would style it with CSS and whatnot.
But this is a little bit messy, and when I come back to
read it later, I may have forgotten exactly how I
structured the date picker.
It's also hard for other people to read my code.
So what we allow you to do is encapsulate this in your own
directive, your own HTML extension.
You could just call this a date picker.
So in your HTML template, you can write, angle bracket, date
picker, angle bracket.
When this code runs, it will expand out into this date
picker that we see in the same way that the more verbose code
did at the top.

And then finally for controllers, I said the
controllers are just simple JavaScript where we get to
associate, maybe, some model with some UI.
And in a very simple example here, again, I'll set up a
piece of HTML at the top there where I've got
some sort of message.
And this is going to refer to a model element named
"message." And then in my controller, I can simply set
up where I can set "message" to a piece of text.
And whatever that text is will appear on the screen.

This is a very brief introduction to the concepts
behind Angular.
There's a lot more to the set of
infrastructure we've provided.
We've tried to create a very complete ecosystem for the
core components in building an application.
Now if you are new to Angular, I did just want to take you
through some of the pieces that we
provide to get you going.
So the first place, I think-- most of you have seen the
front page.
Anyone not?
You just came because you heard it was cool?
OK.
All seen the front page.
So the front page takes you through a bunch of simple
examples to get you going.
If you are learning Angular for the first time, we have a
YouTube channel with a lot of great videos about how to
write code, how to structure you apps.
All the meet-ups that we have here, we put on this YouTube
channel as well.
You can get that from the Angular home page.
If you want to know which applications have been built
with Angular, there's a ton of them.
And if you've got one that you'd like to have featured
here, please send it to us.
We'd love to highlight it for you guys.
And so you can just browse through.
There's a nifty-- actually Brian built this app.
There's a nifty tag sorter, so I can say, hey, I'd like to
find all the apps that support animations.
And you can flip through them and see which ones do.
We also have--
to get you going, after you've gone through some of the
basics, read through some the docs--
there's a tutorial that will take you through all of the
basic concepts in Angular, all the way through to talking to
a server, writing tests, structuring your code.

To get a full deep understanding, we also have a
set of what we call developer documentation.
And in this conceptual overview, we take you through
from all the components of Angular, how we do model view
controller, how we do data mining, we cover all these
things in the concepts.
There's a set of API docs.
We've got a blog, which is the right place to look for
updates, announcements, where we're going to be, when we're
going to do releases, all those sort of things.
And then if you have questions, we'd
love to answer them.
And we've got a really vibrant community
out on Google Groups.
So thanks for listening.
Does anyone have initial questions about any of that?
Otherwise, I'll introduce Brian.
AUDIENCE: [INAUDIBLE]?
BRAD GREEN: Yes.
AUDIENCE: [INAUDIBLE]?

BRAD GREEN: So we don't have what's-- so good point.
So the question was, how do we do animations in Angular?
And we don't have specific supports, although this is one
of our targets in an upcoming release, specific supports for
animations.
But doing just general CSS animations is one of the--
is the way that we do it.
We've got several examples.
As a matter of fact, I wrote--
which one here, this is kind of nifty little game, that
shows you basically how to integrate Angular with
animations, and how to synchronize events with
triggering your animations and whatnot.
AUDIENCE: [INAUDIBLE]?

BRAD GREEN: So we have a number of folks who do mobile
applications in Angular.
And while we don't come with anything out of the box for
mobile elements, there are integrations between Sencha
Touch and jQuery mobile.
The people have built Angular linkages.

Any other early questions?
OK.
Well I'm going to let Brian come up and going to take you
through the main presentation tonight.

[APPLAUSE]
BRIAN FORD: Cool.
So tonight I'm going to be talking about Yeoman.
So who here has heard of Yeoman?
Have any of you used it, tried it out?
Any thoughts on it?
All right, well I've been working lately on adding
specific support for AngularJS stuff in Yeoman.
So tonight I hope to show you some of that cool stuff.
If you're familiar with some of these things like Angular
C, it should be very familiar.
But first, what exactly is Yeoman?
So it's really a suite of tools that take all of these
kind of painful--
just these pain points in developing a web app, and just
handle all that stuff for you.
So one of the big things is when you're starting an app,
you have to bring in all these different assets.
Sometimes you have to configure them so that way,
they work nice together.
Another thing is then when you go to deploy, a lot of us are
using CoffeeScript, Sass, all of these other compiled
languages that need to become CSS JavaScript.
They need to be minified.
They need to do these sort of things.
So that's another thing where Yeoman really helps.
But one of the cool things about Yeoman is it takes it a
step further, and besides just setting up your initial
project, it helps you, say, in the case of Angular, for
instance, it'll help stub out controllers.
It'll hook up routes.
It'll configure things.
So you can really get rolling fast with your application.
And I've seen that there was a lot of interest in extending
these different seeds.
I wrote one for Express that a lot of people started using.
And there were people that took mine, and they added
bootstrap on top of it, or they added a few
things that they did.
And one of the cool things about Yeoman is it kind of
lets you get the best of both worlds.
So you can really quickly get into your app, but you can
also cherry pick the different things that you want to use or
you don't want to use.
So with that, let me clean something up here, quickly.

So tonight, we're going to do something really truly
groundbreaking in that we're not going to use a to-do list
as the demo application.

This is a first for all of us in this--
all right.
So I'm going to make a simple shopping site, like think
Amazon, one of those kind of things.
So you've got a listing of these different items.
You can choose different things, add them to a cart,
and then at the end, it has a little table that shows you
how much money you're spending.
To start out here, I'm in a blank directory.
I'm just going to yeoman init angular.
And so hit Enter, and you get this cute little ASCII
[INAUDIBLE].
And it asks you, do you want to use Twitter Bootstrap?
And I like Bootstrap.
Sure.
And if so, do you want to use it with Compass, as opposed to
vanilla CSS?
This is Compass, Sass--
are you guys familiar with that?
It's pretty similar to Less, or all these other ones.
I'm going to say yes, because I like it personally.
Bigger fonts?
Sure.

All right.
Can you see?
OK, so do I need to make any changes?
Nope.
OK, so that just whizzed by, and it created a bunch of
different files for me.
Most of them are the individual
files for the Bootstrap.
And this seems kind of crazy, but it's awesome because now
you can really easily cherry pick which of these different
features of Bootstrap that you want, and really reduce the
size of your CSS payload.
Down here, you'll see we're
starting to actually generate--
here's your stuff for our application.
So here's AngularJS, we got the shims in here, we've got a
CSS file of simple view.
And below that, we have app.js.
That's kind of your main file.
Index, that's what includes all your scripts.
A controller--
and you'll notice as well, it also generated a
specification.
So one of the other cool things about the AngularJS
support for Yeoman is it really encourages you to test.
So it will--
every time you make a controller or a service or
something that you can reasonably test, it'll say
hey, here's your empty test file.
All you've got to do was go write some assertions.
So that's really cool.
It also creates a testacular config file.
And it also hooks up Yeoman to use testacular to run the
test, because that's what we like to use here.
So now, with all that set up, on the bottom here--
I don't know if you guys can see.
I'm opening up another pane, so that way I can do two
things at once.
This is cut off.
All right.
Well you'll have to trust me.
I'm going to run Yeoman server.

I don't know what went on there.
But anyway, OK, cool.
So it compiled all of our stuff together, and it opens
up the app right here.
But that's not the only thing that it does.
It actually will watch your app for changes.
And so you can really easily just make some change, save,
and it refreshes.
Hi, guys.
I don't know if you can see that.

But how would we use this to actually write an app?
So that's the next thing that we're going to tackle.

First--
I'm going to kill this really quickly--
so first I'm going to make a service that
represents our catalog.
So to do that, we write yeoman init angular--
this is really verbose.
This is one of the things we want to work on.

Service, and the name of the service
is going to be catalog.
And this is going to be a value service, which just
means it's a very simple service.
It's just going to have a static array in there.
In an actual application, you might want to make some HTTP
requests, or something else.
But for the sake of brevity, we're just going to do that.
If we go into our scripts here, we'll--
font up?
All right.
Sorry, guys.

So if you notice down here, this is our index file.
This is index.html.
It included here, scripts/services/catalog.
And here it has this special--
I don't even know what to call this.
This is a wrapper for Yeoman, so it knows to minify and
concatenate these scripts together
during the build process.
And here's our catalog.
So that's not especially interesting.

I have a premade catalog here on GitHub for us to use.

So let me just copy that.

And now let's go to our controller and
actually use this.
Instead of this list of awesome things, we're going to
ask for a catalog.

And just do this for now.
We're going to go back and refactor this.
That way, these names make sense.
But just to show that this actually works, I need to
restart my server.

I don't know.
That was just a weird--

that was just a weird bug of some sort.
I think it's because I deleted the directory and then made a
new one in its place.
And it was trying to watch, or something like that.
But typically, you wouldn't run into something like that.
From here on out, I should be able to work without having to
restart that server.
There are a little kinks in here, so bear with me.
It would be great to have everyone trying this out,
putting in these things so we can continuously improve it.
There's definitely there's a lot of ideas
that we have for features.
But we're also very curious to hear things like,
what do you guys want?
What are your pain points?
So think about those sort of things.
Think about what kind of things do you want generated.
Think about, what are things that I just see myself doing
over and over again?
Obviously, participate on GitHub.
Let me know.

And if you do that, you will get an Angular shirt.
That's your prize for that.
So these are very--
these are much cherished.
So you should--
that should be a good enough motivation.
Besides the furtherment of humankind and all that.

So let's see here.
So we don't see anything in here, but that's probably
because our catalog has these different fields in here.
And our view isn't updated to make sense of that.
So let's do thing, thing.name.

Nope.

Let's do our catalog.

Call item in catalog, do item.name.

I don't know what's going on here.

Unexpected token in catalog.
I'm guessing my copy paste failed.
Yep, there we go.
That'll do it.

There we go.
OK.
So now you see instead of listing that hard-coded thing,
it's bringing in the catalog service
and using that instead.
But this doesn't really look very much like a shopping cart
application should.
So let me go back to my--
I'm just going to copy in some Twitter Bootstrap stuff to
make this look more sensible.

So this is just a header and some of that type of thing.

Cool.
So we've got a basket count there that's not implemented.
Let's just grab that out of there for now.
We're return back to iit later.

Cool.
You can buy things but not really.
And where did our listing go?
OK.
That also doesn't exist yet.
That makes sense.

OK.

We've got this.
Let's make these actually look like we'd expect them to look
on some shopping website.
Bootstrap gives us nice utility classes like as for
this, style equals "unstyled" or something like that.
There we go.
And we also, besides just the name of the
thing, it has a price.
So item.price.
And you see, every time we're doing this, it updates.
Let's use a filter on that.
Let's use the currency filter.
That makes sense.
There we go.

And we can wrap this in maybe a level three heading.
And if memory recalls, there's also an
image for these things.
So item.img.

This is a pretty awesome store, I think.
Let's restrict the width on that.

OK.
So already you can see, we've got quite a bit of stuff right
out of the box here.
I didn't have to go hunt down stuff on GitHub, download a
bunch of files, extract them, move them
around, do all of this.
The application is already nicely structured.
And some of these annoying little decisions about how do
I, you know, how do I structure my scripts, how do I
do these, are already kind of taken care of for you.
And they continue to be maintained when you use Yeoman
to generate all these different things.
Let's go back over here.
I'm going to try this one more time.

We're going to--
can you guys see that all right?
OK.
So we're going to try--

we're going to try overriding the service.
And this is one of the cool things about Yeoman.
So for instance, here, let's see what happens if I try and
generate another catalog.

So it tells me that no, you have a conflict there.
So you can actually look at the diff
right here in console.
This a really cool feature.
I think it just landed recently.
So it's saying it's going to clobber my shopping list and
replace it with this.
So no, I don't want to do that.

But what I do want to do is, I want to add another route now
for a checkout area.
So you can individually generate views and controllers
with Yeoman, but one of the cool things that we have is
this notion of just generating the entire route, which means
you get the controller, you get the view, and it
configures your route provider to use both of those in the
typical fashion.
Obviously if you need parameters and stuff, you can
go in and add those later.
But I think it's a pretty cool feature.
So we're going to call this "checkout."
We're off the screen?
Ah, geez.
Well, I'll execute the command and then I'll scroll back so
you guys can see.

So you get the gist of it.
It created a checkout.js in controllers,
it created the spec.
And you can see the checkout.html it
created as a view.
And that's all it did.
So that doesn't really change what our app is here.
But if we go to--
if we go click on our checkout link here, you see this is the
checkout view.

So that's pretty cool.
Let's also add another service.
This one is going to keep track of which items are in
our basket.
So we're going to create a service, and we're going to
call it basket.

And you guys can see this because it's off the screen.
So let's implement our basket really quickly and then kind
of tie all this together and see how that looks.
So in our services, here's our basket.
We've got a really clever API here that returns
the meaning of life.
But we're going to overwrite that with our own logic now.
So we'll call this "basket."
This is going to be a local representation.
We'll have kind of getter and setter kind of things.
So if you get this, it's just going to return the basket.

If you want to add an item such as one that we defined--
that's not supposed to be a factory--

such as one that we have in our catalog, it
will take an item.
And if the basket has something with the same idea
as that item, then we are going to increment the
quantity of that item by one.
And otherwise, if there's nothing in the basket then
we're going to create it and set its quantity to one.
So it's going to look like this.
The type of the item will be equal to a reference to the
item in our catalog.
And the quantity will be one.
All right.
How does that look?
So far, so good?
Again, this will keep refreshing every time, but
we're not really doing anything new.
So to remove the item, we just delete it out of that--

we just delete it out of the object that we have here.
So delete basket item.id.

Let's make it so you can actually add
things into this basket.
So back in our controller, our main controller we should ask
for a basket.
And let's just expose it right on the scope.
Scope.basket = basket.
OK so with that in mind, we can go back to
our view for main.
And we can add a nice button.

Let's give it a btn-primary.

That should be the nice blue button, I think.
"Buy." Cool.
So it doesn't do anything yet.
But it will soon.
So let's add an ng-click.

And we'll have that be basket add whatever the items.

So presumably this is working.
But let's implement this checkout view over here, so we
can actually see what's in our basket.
So this is the checkout view.
Yep.
That it is.

So we're going to have another unstyled list-- actually,
let's make this a table.
I like that idea better.

It's a table.
So we'll make--

we'll make the head first.
What do we want to do?
Maybe item, name, price, quantity.
Let's navigate over here so we can actually see these things
updated in real time.
Then let's do--

let's repeat over this item in basket.

And let's get the item.type.name, and the price,
and we'll use the currency filter.

So let's see if this is working.
One of the things is, right now, all of the stuff that
I've written is just right in memory.
So every time it refreshes, you get kind of a clean slate.
So let's see.
I'm not seeing anything.
Why is that?

Item, quantity--

OK.

Try to buy something, and it's not in checkout.
And I don't have my Batarang either, so I can't easily
debug this.

Let's add a title here, and I'm just going to keep
thinking about what exactly went wrong there.

I should write a test.
That's a good idea.
Who said that?
That guy gets a t-shirt, I think.

The issue is actually, I just realized, that I'm not getting
the basket.
So, go back to our catalog, add an item, go to check out.
No, still not there.
OK.
Yep, you're right.
We're going to write a test.
OK.
So we load--
let's look at our basket.
So we load the shopping app module, and then we inject the
basket, and we should be able to do these assertions.
So it should initially be empty.
Basket get toBe--
get.length, maybe--

toBe true.
This will expect that to be zero.

Now we can do testing.
So Yeoman test and this is just typing it right back into
testacular.

It's being very slow for some reason.
Hopefully that's because it's finding all of my bugs.

This is actually using, or it should be
using, phantom, yeah.
That's what I've configured to do it by default.
But you're right.
Let's see what it looks like if we go into our--
where's our testacular config?
There it is.
So let's do Chrome instead.

There we go.
OK, cool.
So it actually crashed.

That's good if this tells me-- expected undefined to be zero.
So we're not returning anything in git.

Return basket.

There you go.
That was it.
I'm glad someone's paying attention.
OK.

It should, hmm--
all right, so we have to write our own length.
So let's do a count.

ToBe 0.
And what does this look like?

Yeah, we could enumerate over object keys.
But I have a different solution in mind for that.
So we're going to just keep track of a count.

And whenever you add an item successfully, we're going to
just increment that count.
And whenever you delete an item, we're going to--
huh?

We're going to do that.
So hopefully that'll at least to yield a
test that is testable.

I still have to expose the count?
Oh, yes.
Good call.

That's also an approach.
But there's a reason I'm doing it this way.

Is our test still checking no?

I got it.
I got my parentheses in order.

It's swiping back and forth because it's popping up a--
Chrome really quickly.
So it doesn't see--
controllers main on line 20--
That's interesting.

Which one is main on line 20?
What's going on there?

Oh, OK.
So we're actually failing a test that expected our awesome
things to have this length.
That's interesting.
OK.
I'm going to comment that out for now.

OK.
There we go.
Now we get success.
That was a red herring.
That doesn't--
Yeah, you can.
Sure.

Where is my test?
So, my test for basket, if we just want to run this one, you
can do i it.
And we can run this again.
It'll do the back and forth.

Yes.
So there, you see it only ran one and
skipped the other three.
And that one passed.
So--

uh, not yet.
Is that something that you think is a god idea?

Possibly?
What do you guys think.
Do you guys like the--
you guys who are using testacular, do you use the--
the i it or the d define?
Or is--

yeah.
Yeah, all right.

So you think in testacular maybe this is a thing?
Someone get [INAUDIBLE]
now.

So you still have yet to see this work correctly.
Let's see if anything I did there made any difference.
Nope.
All right.
We're going to go grab--

Chrome store--
what was that?

Probably not, but that's what I'm going to see right now.
I'm going to grab the Batarang extension.

Let's install that.

So now if I--

all right.
So what's going on here?
So this has a list of awesome things.
And now it's clear why this doesn't work.
The answer is that I didn't ever expose this on my scope.

So eventually I would have caught that if I wrote the
unit test for checkout control.
But I'm apparently being impatient today.
So let's just expose the basket.

And hopefully, when we add an item, there we go.
Now we actually see it.
Thank you.
Thank you very much.

Let's make this look nice, though.
We can go back to--
geez, it's so hard to work at this resolution.
You develop on a 30 inch monitor for a while, and then
you present on this thing, and it's a major headache.

If someone wants to invent, like, a super high resolution
monitor, I would buy like 10.
It's a good start-up idea.
So let's make this table look nice.
So I think it's class="table." It's very fitting.

That's pretty looking.
Doesn't have anything in it yet.
Let's maybe conditionally hide this.
So ng-show--
we only want to be showing this when basket.count is
greater than zero.

So let's close that up.
And maybe otherwise, we show a nice message like, hey, you've
got to buy something or get out.

Let's just do, when it's equal to zero, no items in basket.

There we go.
Now we have a nice message there, so our user isn't too
confused, hopefully.

Let's go back over to the cart.
We've got this kind of primitive looking thing here,
but let's say we want to group all of this item together into
a directive.
So there's a generator for that as well.
And it's aptly named Angular directive.

Yeah.
I'll do that.
That's a--

all right.
Sorry about that.
Thank you for the suggestion.
so we'll call this, maybe, product.

And let's go move all of this stuff right here
into its own directive.
Do we want a Buy button in there?
We can put a--
eh, we'll leave the But button out of there.

So we'll put that into a template.

That looks pretty good to me, except we need to expose on
the scope an item.

And we don't need this link function.

Then we can go back to our main view.
And we'll use "product" here instead.
Item="item." That seems like it's still working.

See it?
There we go.
So we can see that we now have this item.
Can you see that?
So it looks the same.
But we do, in fact, have that item directive there.
So this works.
We can click on these different things.
But it would be really nice if we actually had some feedback.
So maybe we'll put something up here that shows us how many
items are in there.
So let's go to--
let's go back to our index.html.
And we need another--

we need other controller in here to show us how
many items are there.
So I'm just going to add it in here. ng-controller equals--
we'll call this NavCtrl.

Now over here, it refreshed.
And it doesn't actually have that yet.
But I can use Yeoman to generate just the controller.
So there's no route for this.
It's just the controller.

So that looks nice again.
Let's expose what we need to on nav and then just put the
count right in there.
So we want to expose the basket again.

Sorry, what was that?

It's overriding this?
Oh, you got it?
Right.
No worries.
If you guys have questions, feel free to chime in.

OK, so let's go back to--

back to our main--

back to our index, rather.
And up here in checkout, we want to show the number of
items that we have.
So it's basket.count.

So we have zero, click on a few things.
And then we have that.
So let's finish up this checkout page.
We probably want a total here, and maybe a
total column in there.

I'm just going to close all these because I can't read
them anymore.

Back in checkout, let's do item quantity.
We'll do subtotal and
item.quantity times item price--

type.price, rather.
And we'll use currency.
So that looks nice.
This is one of the tedious things.
If we had a persistent data store, this
wouldn't be an issue.
So there, we've got the subtotal in there.
Let's add something to our checkout controller that can
sum this up.
So, call it scope.total maybe.
It's a function of--

there's a nice Angular utility that will let you do forEach
over the object without having to think too hard.

So, basket--

and we need to keep track of the running total, so--
I'm not very inventive with variable names today.

So we want the item type price times the item quantity.

And we want to put that maybe down here at the bottom.

Maybe we want to make this bold.

OK.
So let's try that.

Ooh, not working again.
All right.
So this is going to be a race now.
Let's see who can figure out what my mistake was.

I didn't return the total.
There we go.
Who said that?
Excellent.

I didn't use CoffeeScripts.
Ugh.

I actually learned CoffeeScripts just that way I
could have Yeoman generate CoffeeScript.
So, for instance now, if you wanted to have--
I'm not going to do this, but--
coffeeThing--

if you wanted to do this, it'll actually generate
CoffeeScript for you as well.
And then it will compile all of this.
As you notice down here, it's compiling it.
Or maybe failing to compile it or something.

But anyway, in theory it works.
Now that we're turning--
oh, man.
What's going on there?
So we return our total.

Maybe just the console will tell me what's wrong.
Failed to load resource.
Oh, it doesn't like this CoffeeScript thing.

Sorry, CoffeeScript guys.

That was probably my bad, not CoffeeScript's bad.

Price of undefined.
Check out line 8.

Price of undefined.

We have to do basket.get.

There we go.
Awesome.
All right.
Well, thank you guys for helping me out there.
I'm glad that you're all paying such close attention.

OK.
So that's the basics of it.
And you even got to see me do some ad hoc testing to try and
figure out where I messed up.
Do you guys have any questions so far?
What do you think?
Yay, nay?
Would you use something like this?
Is it cool?
Yeah, question in the back?

Right, so the question was, if you had something in this
checkout stage that let you add a gift card, you could
really easily update it.
You could just apply it right there.
Yeah, that's definitely the case.
Do you want me to write something like that?
Yeah, you want me to write it?
Yes, I'll do that but--
your question?

Yeah, sure.
So you want to add for--
oh right, the question.
Sorry, the question is how easy is it to add support to
Yeoman for some other library, or add some
new features to it.
The answer is it's actually pretty easy.
Yeoman builds upon Grunt, which is another pretty
popular build tool.
And it combines a couple modules of Grunt.
And it also adds a bunch of other custom things.
But if you check out the Yeoman API, they've got some
guides in there for doing it.
Do you want to see what the code looks like real quick?
Can I find my own code?
This isn't actually my computer, so it's hard to
figure out where things are.
Look at the generator code really quickly here.
So if you want to add your own library here, we've got--
I don't know if you guys can see it that well-- there's
Angular, Backbone, Chrome app, Ember, Jasmine, Mocha,
Testacular, Yeoman.
So let's just take a look here at, for instance, our
controller generator.
So this gets a name from its inherited class, basically,
and it makes sure that you don't have controller already
on the end, otherwise it strips it off.
And then here, it just copies these template files.
And this is just really smart, and it knows what
its own name is.
And so it will fill in the different gaps.
And I think I can just pull up right here really quickly.
So there's a set of CoffessCript templates and
JavaScript templates.
And so in order to write a controller, you give it--
I don't know what style this is.
Is this EJS, or one of these?
Anyways, it's just a--
sorry.
Does someone know?
Herb.
All right, so herb style string interpolation here.
And it just uses the properties of the generator,
most of which Yeoman just gives for you out of the box.
It will parcel out the command arguments and do all of these
sort of things.
You can customize the different arguments.
So it's pretty easy.
Like, if you had some pattern that you used for building
services, for instance, and you wanted to make it really
easy to do that, you could easily add it yourself.
It would be no big deal.
And then you could send a pull request.
And I'd be like, that's awesome.
And then you'd be internet famous.
So you should do that.
And you'd probably get a t-shirt for that.
There's all sorts of--
FEMALE SPEAKER: Is there a way to get--
sorry.
Is there a way to get Yeoman to tell you what Angular--
what you can do from the command line for Angular?
BRIAN FORD: That's a good question.
Yes, but I think it's kind of broken right now.
So you can do --help.
And I think that this just lists what the Angular nit is.
Oh, here, it has some of these things.
But it's not actually parsing all of them.
This is a non-exhaustive list.
I'm not sure why it's non-exhaustive.
But anyway, I have a write-up on my blog--
it's briantford.com--
about all of the different things.
I imagine that very shortly that particular
issue will be fixed.
And in fact, if someone in the audience, on your laptop, if
you want to file a GitHub issue right now.
Working on it tonight, even.
So yeah, that type of functionality will be there.
And I don't know why it is.
I think it's the way that Yeoman is generating that list
right now is it just looks at the top level generator when
you do yeoman init angular, and it just grabs all the ones
it uses there.
But by default, I'm not making any services.
I'm not using all the different options.
So yeah, that's a good point.
That would be an excellent feature.

And let's see, you wanted to see if I were to--

yeah, like a code or something.

Oh, I see.
So how would I do something like that?

Yeah.
I'll repeat the question.
Thank you.
So he said, what if you had an app where you put in some gift
card amount, and you wanted it to decrease over time.
So I'm not actually going to write all the code.
I thought it was an at checkout time, that he wanted
me to have a code, one of these put in your gift card
code kind of things, which is easy.
But something like that, I would maybe
create another service.
And then every time you're withdrawing from it, you're
calling some function.
And it only does the transaction if you actually
have balance left.
And you can hook it up-- you can write this service that
way it will communicate back and forth with your server.
And so you can do all sorts of crazy things.
But tonight I just wanted to show some of the basic
features of Yeoman.
Show how it relates to Angular and hopefully spark you guys'
imagination, and we can add some other cool
features to it as well.

How do you install a new version of Angular?
So I think some of the guys at Twitter that work on Bootstrap
recently released this tool called [INAUDIBLE], that also
is kind of subsumed by Yeoman.
And right now--
right now, we don't have--
it it's not integrated fully yet.
But what it'll look like very soon is, you'll just Yeoman
install, for instance, Angular.
You can do it right now, but it's not--
it doesn't wire everything up correctly
for you like it should.
So it grabbed Angular, and I think it makes a
components file here.
And then what you'll do when you want to update it is, you
can Yeoman updates Angular--

update, upgrade, something like that--
fatal.
OK.
So I guess that means that we have the newest or something.
A lot of this stuff is really bleeding edge, and you have to
npm install at latest and do these things.
But this is why we want to get feedback.
I'd really be interested to hear from you guys, like what
sort of things have you automated?
What's your build process like?
When you set up a project, what are
you're tools of choice?
These are the kinds of things I like to know more about.
Because obviously, I have my tools, but we want to make
this thing really awesome.
And we want to make sure that Angular is able to integrate
with all these libraries really seamlessly.
And hopefully, this'll be kind of the catch-all for these
different seed projects, so we don't have to have every
permutation of every JavaScript library ever, and
every CSS skeleton library, and all these things.
Instead, you should just be able to pick these things and
then run the generators, and everything kind of just works
really great together.

But we're not quite there yet, as you saw me stumble.

Anything else, guys?
MALE SPEAKER 1: Do you guys have any suggestions?
Anything that you use every day, but you haven't seen
today, and you would like it to be part of Yeoman?
FEMALE SPEAKER: It would be really cool if you could do
something with modules, and sort of recommending how to
layout modules in an app.
BRIAN FORD: Right.
That's very good point.
Right now--
right now--
so to be honest, I spend a lot of my time building tools for
Angular, and not quite as much time using Angular to build
huge scale applications.
So actually, I imagine many of you guys in the audience
actually have valuable experiences that I would love
to hear about.
I'd love to hear about what your strategies are for
different modules.
Right now, what I would recommend if you're using
Yeoman, is you would in your--
gosh, that's the wrong thing entirely--

in your app.js, I would just define all of
your modules there.
And then, I guess, one of the advantages of putting things
in modules is when it comes time to test, you can reduce
the amount of things loaded.
So I would group together things that kind of visually
go together, or they're on the same page, or you would want
to cluster them into a test.
Some things that we've been looking at are, do we want
lazy loading modules?
Do we want to integrate with RequireJS or ES6 modules, or
these sort of things.
And there's just an explosion of options in that space.
So it's really hard to nail down what does everyone want?
What's the best solution?
What's the generic solution that just wins across the
board for everyone?
So again, that's a very good point.
Yeah, we definitely--
right now, there's no generator.
There's no anything besides--
here's your default module, here's your
application level module.
And if you want to add your own things, you kind of have
to maintain that all on your own.
But again, let me know what you guys are doing.
Let me know how you think it should work.
And hopefully, we can come up with an awesome solution.

All right, so the comment was, it'd be nice to support
Minifier and Obfuscator.
So you're right.
At the moment, I think that all this does
in the build step--
I've been away from this.
I actually just merged a ton of changes.
I'm a little bit behind.
I believe that all that we're doing is concatenating
together all of the files.
But yes, minification, definitely coming soon.
Angular has a few special considerations,
in that if you use--
you have to use the long array from annotation.
And something that I'm looking into now is something that
takes the short form and just automatically produces the
longer annotations before sending off to the compiler.
So that way you don't have to do all of that yourself.

Do you guys know I'm talking about?
Like, when you write--
OK, here.
So here's an example of the long form, where we've got--
you've got the array.
This is the string here, so that way this doesn't get
minified out.
And then over--
if I can find the controller somewhere--
over here, we've got the short form.
So really, a much better solution I think would be less
typing for the user, but still super minifier friendly.
So that's something that I think is cool.
What do you guys think about that?
Good idea?
bad idea?
Do it?
Great idea?
Should be done yesterday?
That kind of thing?
All right.

Yeah, I def--

Yeah, you don't one giant file.
So there's a lot of different strategies
that people are taking.
Like, some people want to lazy load files.
And there's also this entire additional problem of how do
you deal with third party libraries that are using
different wrappers?
And so it's very complicated.
And I want to make sure that the things that--
or the tools we're building on Angular are awesome and work
well with all the sorts of tools that our people that
come to our meetups, and use our library, and participate
in all of this are really excited about.

Yeah.
Actually that's a great point.
So right now, Yeoman actually already does that.
It already versions the filenames for you.
It does that when it concatenates them.
And then it minifies it and I think it--
I think it preserves it at that step.
But anyway, I know that's something that you don't have
to define it on a per framework level in Yeoman.
Yeoman just kind of takes care of that.
But yes, that's very good.
Yeoman also does some cool stuff, like it
generates app caches.
I only just barely scratched the surface on some of the
different cool things that Yeoman can do for you.
So I would urge you guys to check it out.
I would urge you to also file issues.
Something's crashing, something's not working right,
you don't like how something works, you have an awesome
idea, like all those things.
Please just--
right now is really when we want to
collect feedback on this.
So I can't urge you guys enough.

So what is the relationship between Google and Yeoman?
That's--
is that a Brad question?

All right, sorry.
I don't know what's going on now.
Yes, just repeat the question.

All right, what's the--
what's the relationship between Google and Yeoman?
So Yeoman is totally open source.
It's all on GitHub.
It's all developed there.
If I understand correctly it's a project started by, I think,
Paul Irish and Addy Osmani and some of the Chrome Developer
relationship guys.
But I know that there's a lot of people outside of Google, a
lot of these big open source--
what's the guy's name?
Anyway, there's a lot of open source involvement too.
And if you have some library, some feature that you want to
add, just get involved.
It's pretty straightforward.
Again, it builds upon tools like Grunt, which I think a
lot of people are familiar with.
You guys know Grunt?
All right, cool.
So it should be pretty familiar, if you're using
Grunt, if you're using these seed projects.

I don't know.
Is there anything that you have in mind?
You excited to contribute some awesome feature?
MALE SPEAKER 2: Our company is using JavaScriptMVC.
So I don't see any JavaScriptMVC on your Yeoman
thing, so just curious of that.
BRIAN FORD: I see.
That's all I got on that.
MALE SPEAKER 1: So maybe he can switch to Angular.
[LAUGHTER]
BRIAN FORD: Hopefully--
my performance on the tools tonight probably didn't entice
anyone looking to switch.
But it's getting there.
And I think that it says a lot that we're really trying to
create these kind of tools.
I mean, it's really a difficult space.
It doesn't take a lot to combine Angular and Bootstrap.
But it takes a lot when you scale it to
like, n different libraries.
And there's all these different ways
that things can intersect.
And that's again why you see all these different things
breaking, because every day we're finding some new and
better way to do something.
And every day it's breaking my generators in
my build and stuff.
I'm always playing catch-up.
MALE SPEAKER 3: I had a general Angular question which
may be solved by a Yeoman feature.
BRIAN FORD: Sure, I'd love to hear it.
MALE SPEAKER 3: Which is handling localization and
globalization in Angular, what the best practices is.
It seems like you either get clobbered upfront by loading a
big file, or it's a death by a thousand cuts, as you go back
and try and load up resources for each little thing.
So maybe adding a compilation step in that allowed you to
load in a globalization or localization file.
BRIAN FORD: Yes, that's a very good point.
And again, that's not something that I specifically
have a ton of experience with, but one of you guys--
no?
I know we have a service that helps with localization, but
again, I haven't specifically used it.
That's--
MALE SPEAKER 1: So I think I can answer some of that stuff.
We support, I guess localization is the word.
In other words, if you're in a different locale, you want to
format the strings differently, the numbers
differently, currency differently, and so on.
We also have this pluralization directive, which
allows you to deal with things like one file, or two files,
or zero files.
But when it comes to translation, you're
essentially on your own.
And that means that you have to actually produce different
versions of the template.
So you would have--
the same template would have to be fed through a translator
so that you would have it in different languages.

Yes.
So microphone--
FEMALE SPEAKER: We have a question from [INAUDIBLE]
talking.

BRIAN FORD: Voita chimed in and said that he also thinks
that that's something that should be done on the server
side, combining together these localization resources.
So is that is the general consensus?
I mean, I don't foresee a lot of situations where you have
to display something in Chinese and then switch to
Spanish midway through.
Typically your users are pretty deterministic in what
language they want to see.

MALE SPEAKER 4: [INAUDIBLE]
right off.
But let's thank him for the presentation tonight.

FEMALE SPEAKER: Do we time for one more
question from Seattle?
MALE SPEAKER 4: We did have another presenter, but he has
not shown up tonight, so we're going to be here to answer any
questions you guys might have.
So please come down, chat with us, and we'd love to hear
other thoughts and have discussions with you guys.
Thanks for coming.