AngularJS Intro + Dependency Injection (AngularJS Meetup SF 2012-07-17)


Uploaded by angularjs on 11.09.2012

Transcript:

BRIAN GREEN: Hey, welcome everyone.
Thanks for coming.
MALE SPEAKER: Can't hear you.
BRIAN GREEN: Oh.
Hey, welcome everyone.
Thanks for coming.
MALE SPEAKER: Are you miced?
BRIAN GREEN: That mic is on.
I think it doesn't amplify that much.
Can you hear me now?

If I talk low like this, can hear me then?
Is that better?
Still not better?
No.
OK.
I'll just talk loud, and maybe over here.
This is our first AngularJS speed up for San Francisco.
We've done them in many places--
Mountain View, New York, Seattle, and Prague, I think.
But, first one in San Francisco, so thanks so much
for coming out tonight.
We're going to do a couple things-- is that better?
MALE SPEAKER: Yes.
BRIAN GREEN: Ah, OK.
Igor solves the problem.
We're going to start out with an introduction.
For those of you who haven't used Angular before, how many
of those are you?
I've never written an Angular app before.
Good, good.
Many of us.
Good.
OK, so we're going to walk you through what we think are the
coolest bits.
Igor is going to do that.
And then we're going to deep dive into something we think
makes Angular special.
There's a lot of special parts about Angular.
And Vojta, who's just walking in with his backpack there, is
going to take us through some of that.
So we're going to keep this kind of short.
For those of you who have written Angular apps, how many
of those folks are here?
We do want some time to hang out, answer questions.
If you've got code here, we're happy to work on it with you.
Igor over here, Brian, and then Mishko-- where'd you
go?-- are the founders of the project.
And Vojta can help you with code questions.
I'm the manager.
I'm Brad Green.
I'm really happy to see so many people come out for this.
This is awesome.
I'll let Igor take it away and introduce [INAUDIBLE].
IGOR MINAR: I would like to introduce Robert.
Robert, can you come just for a second?
So the Angular team is located in Mountain View, but Robert
is from San Francisco, and he offered help with running this
meetup here in San Francisco.
So I'd like to thank him a lot for doing this.
[APPLAUSE]
IGOR MINAR: We would like to meet here monthly.
Robert is going to take care of hosting you guys here.
The Angular team, we're going to try to come.
I'm not sure that we'll be able to come for every single
meetup, but we'll definitely plan for coming here and
visiting you.
But this meetup is all about you coming together and
talking about Angular, making contacts, discussing problems,
offering solutions to each other.
So the reason why we're here is for you to get to know each
other and help each other.
And also, we are here to help you, as well.
But please greet your neighbors and make contacts.
Thank you, Robert.

So again, my name is Igor, Igor Minar.
I'm a software engineer at Google, and I'm the team lead
on the AngularJS project.
And we're going to talk a little bit about Angular, and
why Angular exists, and why would you want to use it, and
what makes Angular special.
So everybody here knows what a browser is, right?
Right?
MULTIPLE SPEAKERS: Right.
IGOR MINAR: Yes, yes.
We use them every day.
And it's interesting that when you look back not too many
years ago, browsers looked something like this.
And they were very simple.
And the content that they used to display was very simple,
static, quite frankly, boring.
So that's why it's incredible to look at the browsers today.
And we see something like this.
We run all of our emailing, calendaring, we watch videos,
play games.
And craziest of all, we can run a full
blown IDE in the browser.
So as a user, I feel really good about the current state,
and I can use these rich applications.
There's a lot of content.
Everything's really good.
But unfortunately, I can't say the same as a developer.
The reason for that is the complexity associated with
building these really rich applications.
And as you probably know, complexity kills.
Complexity kills creativity, and it creates this huge
barrier between you and the user you're trying to build
this awesome app for.
What do I mean by complexity?
Well, let's take a very simple example of a hello, world.
We can implement it in HTML and then in JavaScript.
So in HTML, it's very declarative.
And you're basically telling the browser, hey browser, I
want you to render a paragraph, and I want you to
set the content of the paragraph to be hello, world.
We are not telling the browser how to do it, we are telling
the browser this is what we would like to do, this is the
end result--
and it's up to the browser to figure out how to do it.
Now let's compare that to the JavaScript version of the same
application.
You have to understand how browser works.
You also have to understand which events to listen on.
How to register the even listeners, how to do the DOM
manipulation.
Unfortunately, you also have to understand the differences
between browsers and work around those.
But worst of all, this is a sequence of steps that you're
telling the browser to take, and as a side effect of taking
these steps, the hello, world will be displayed on the page.
So I used to build applications in this way, and
I often felt like I was dealing with black magic, like
I was tricking the browser into doing things rather than
asking it to help me build this application.
Anybody here remember how we used to do rounded corners
before we had border-radius?
Like all this nested data and the images--
that was just nuts.
We were tricking the browser.
CSS has improved.
We can express annotations better.
Unfortunately, we don't see the same kind of improvements
happening in the DOM and HTML APIs.
But you might say, I use jQuery and everything's good--
like, I'm this jQuery ninja.
But my answer is, not really.
Things are not so good, because jQuery is very
imperative.
And if you think about it, jQuery shouldn't have existed
if the browser APIs were sane and were implemented in a
consistent way.
The solution I'm looking for is declarative.
And just like a hello, world example, but something
suitable for building applications rather than
static pages.
If you have WPF or a [? Flex ?] background, you
know that data binding solves this problem really nicely.
In data binding, you have a model, you bind the model to
some template, and let the templating engine figure out
how to merge the two and how to keep them in sync.
So as my model changes, the view is updated by the
templating engine automatically.
And as my user interacts with the view, the model will be
updated for me by the templating engine.
So if the user enters something into the form, the
updates just propagate to my model automatically.
I don't have to do it.
So what you get out of this is this spreadsheet like system
where the updates just happen.
Everything is just recalculated on the fly.
And you don't have to write too much boilerplate code
because you can describe these bindings in a
very declarative fashion.
But this can get even more interesting when you have a
collection.
In my case, I have a collection of three
superheroes in an array.
And I'm going to bind it to a very simple template using a
looping construct, and the templating engine will just
figure out how many copies of the template it needs to stamp
out, and how to data bind each element in the collection to
the right copy of the template.
And what I get is just a nice list of superheroes.
But more importantly, I also get this
spreadsheet like update.
So if I update the model, I push a new superhero object
into it, or if I change some existing superhero in the
collection, the view will just update for me without having
to do anything.
So data binding is really awesome, and it can remove a
lot of boilerplate from the application.
Because if you look at the typical application, you'll
notice that about 70% to 80% of the code is just about DOM
manipulation.
I'm talking about the client side code.
So DOM manipulation, listen in on events, updating the DOM,
keeping the view and the model in sync.
With data binding, all of this goes away.
But you might say, but data binding doesn't exist in
JavaScript or browsers.
What am I talking about?
Well, if you use AngularJS, you can actually benefit from
data binding because we extended HTML and we added
support for data binding to HTML.
You can use it today with current browsers, including
IE8 and mobile browsers.
So you can totally do it.
But we think that data binding is so awesome that there
should be native facilities in the browser.
And that's why we're working with a team at Google, which
is in charge of creating a specification that other
browser vendors then look at and implement.
And we're working on a specification called Model
Driven Views.
The goal of this specification is bring native facilities for
doing data binding to the native platform.
That will be more efficient.
It's going to be just awesome.
It's going to take time to get this done, so I wouldn't waste
time waiting for MDVs.
You can use data binding with AngularJS today.
So data binding can help you with a JavaScript boilerplate.
But what about the HTML boilerplate?
Because HTML can be verbose, as well.
Let's take a great example of Twitter Bootstrap.
Everybody knows about Twitter Bootstrap here?
Yeah, I love Twitter Bootstrap.
It just makes my HTML look badass by default.
And unfortunately, if I want to render tabs like that, I
have to go to the Twitter Bootstrap site and go find the
tabs component in the documentation and copy and
paste a big chunk of HTML like this.
It doesn't even fit--
it's cut off.
And find the places where I need to put my content.
And then I get the tabs rendered.
So I feel like this is not the right thing.
It's not very maintainable, this copy, pasting business.
It just doesn't work for me.
And worst of all, I'm, again, tricking the browser into
rendered tabs, rather than asking it for rendering the
tabs for me.
What I want to do is, in my HTML, I just want to say,
browser, please render tabs.
There are these panes with this
content with these titles--
you figure out how the DOM needs to be constructed to
render it as tabs.
I'm just telling you to render tabs.
This is what we call reusable components in Angular.
And it's a feature that we edit, and you
can use it in HTML.
So this is how we extend HTML.
And it's not just tabs.
You can reuse, you can create any kind of component that is
suitable for your application.
These components can be simple and stateless, or very
complicated and stateful.
And you can reuse this component in your application,
as well as if you have a large organization, you can reuse
them across different projects in your organization.
Or in case of tabs, you can just reuse them with many
other developers outside of your organization.
So it's really up to you how you use this feature.
We implemented this in AngularJS using existing DOM
and JavaScript APIs.
And it's available today in all of the major browsers
including IE8 and mobile browsers.
We think that this is, again, a really cool feature and
should be part of the native platform.
And that's why we're working with another group at Google
that is working on the web component specification.
And this specification will bring similar components
directly to HTML and the native platform, and they're
throwing in some extra features that we can't do in
JavaScript because it's just not possible to implement them
using the existing APIs.
This spec is actually currently being already
implemented in WebKit and Chrome.
So if you have [INAUDIBLE] builds, you can start playing
with parts of the specification.
It's really cool.
So I showed you two things.
I showed you data binding, and I showed you reusable
components.
These are just two ways how Angular tries to make the
existing browser smarter.
There are other things like routing, persistence, talking
through the server side, all kinds of other things.
But I would like to show you what a development with
Angular looks like.
So let's do some of that now.
And again, I'll be happy to answer any
questions you might have.
So just come to the microphone over there, or I'll leave a
microphone in front here.
And just ask questions if you have any.

All right.
So the best way to start with Angular is to visit our
website, angularjs.org.
We have lots of examples on our website where you can see
and get a feel for how things work.
You can play with the applications right
there on the page.
We also have some screencasts for many of the examples, too.
So you can see how we actually build them step by step.
Our documentation is also a pretty good.
All the APIs are covered with examples and tests.
And there's also some discussion, so if you have
questions, you can ask them there or on the mailing list.
We have a really nice and growing community, and they'll
be happy to answer questions on the mailing list.
So you can go there.
If you're wondering who uses Angular, the biggest
application that we released and we can talk about is
DoubleClick.
DoubleClick is part of Google that interfaces with many
advertising agencies, and it's in charge of generating a
couple of dollars for us.
So it's an interesting team to work with.
They've been working with Angular for the past year and
a half, and they have a lot of experience.
I'm actually hoping to get the team lead of the project to
come talk at a meetup either in New York or Mountain View,
and we're just going to record it so you can see it as well.

So the application I'm going to build is something you
haven't seen before.
It's a Todo list.
Because nobody builds Todo lists these days, so I thought
I would implement one.

Right now what you see is a static page.
And actually, it doesn't even work because in order for me
to start, I need an HTP server.
So this is just a simple, static HTP server.
There's nothing going on.
The server side is just serving static files.
Oops.

Ready.
And if you look at the code, you see that it's just a
static HTML.
So we have a HTML5 document that is loading some Bootstrap
CSS, so the application looks nice.
And then we have AngularJS, and we have a Todo JS, which
is a file where all the application logic will be.
And then we just have static HTML for our documents.
So some headings, some paragraphs, static list of
tasks, and then we have a form that doesn't do
anything right now.
So how could we turn this into an application?
In Angular, it's quite simple.
You just go and put ng-app somewhere in the document.
You put it at the root of the application.
So you can actually have it somewhere
lower in the DOM tree.
If you have a round tree application, you can just say
only this portion of the document should be Angular
application.
But let's put it on the HTML tag.
And I could do something like this now.

Username.
And if I save, you see that there's nothing here.
The reason that there's nothing here is that we
haven't defined the model yet.
And just to show you what it looks like without ng-app-- so
if I remove ng-app and save it, you see that we just see
the raw template.
We see the double curlies there just by adding ng-app.
Angular knows that this is an Angular application and goes
and compiles the template and does the right thing.
So for us to be able to actually render the username,
we need to provide some context.
And this context in an Angular application is defined through
a controller.
So I'm just going to go here, I'm just going to say ng
controller equals--
I'll call it app controller.
OK.
This still doesn't work because app controller should
live somewhere.
In Angular we have a module system, so we're going to just
say that all the pieces of our application are going to live
in a Todo app module.
If I save it now, it works.
The reason why it works is if you look at the Todo JS.
Is this big enough?
Can everybody see?
Yes?
No?
OK.
So if you look at the Todo JS, you see that we are defining
the module.
And then we have a Todo app module.
And on that module we have defined a controller called
app controller.
So this is what the app controller in the template is
referring to.
And the app controller is really just a very simple
constructor function which takes one argument called
[? dollar scope ?]
and does some interesting stuff here.
For now, just think about [? dollar scope ?]
as a context, a context that is shared between the
controller and the template.
And using this context, we're w to publish the model so that
it's available to the templating engine.
So we take the scope object and we're going to assign
username property.
Username is something that we defined in our template.
And we're just going to say that the value of this model
is Igor stream.
So now if I go here and I refer to username, we know
where that comes from.
OK.
That was pretty easy.
Let's take this list and turn it into a dynamic list.
So that we can have some model and we're just going to shrink
or extend this list based on the number of elements in our
collection.
So what I need to do, I need to create a template that we
can then clone for each of the elements in our collection.
And to do that I'll just use another construct, ng-repeat.
I'm just going to say item in items.
If I save, you see that we have two new tasks here.
So I can throw away this static list because it's too
boring for us.

And we're just going to focus on this dynamic list.
And the reason why we have task one, task one is because
we did a data bind to the model.
So I'm just going to say item dot text, and you see that we
now have two tasks with different names.
The reason why we have two tasks and a place where the
model comes from, we have to go to the controller
to find that out.
So in our controller, we have a very simple native array.
Notice that this is not some Angular API.
This is just a JavaScript array that contains plain old
JavaScript objects with text and DOM properties.
And we have two of them.
That's why we have two tasks in the view.
And we're going to take this items array and we're just
going to publish it on Scope as a model called items.
And that was all that we had to do to render the list of
the two tasks.
Now, if I wanted to see what's the value of the DOM property,
I can just do this.
And now I see that one is false, one is true.
The check box doesn't reflect the state of
the task right now.
The reason for that is that we didn't data bind it yet.
So let's use ng-model and say item.dom.
So we're going to bind it to the DOM property of the item
where item comes from the collections of the temporary
variable SVF iterating over.
And now you see that checkbox is checked and data binding
just worked.
So as I'm interacting with the checkbox, actually, this
outdated binding is being updated, as well.
Let's remove this.
And let's focus on this part.
So how can we get that going?
Instead of this placeholder, I want to say, render the
current length of the array.
Array already has a length property, so I can just do
items.length.
And when I save, you see that I have two now here.
Perfect.
That works.
What about remaining?
Array doesn't know anything about task or status of done
or not done, so we have to create
something application specific.
And I'm just going to create a method called remaining that
will calculate this information for us.
And when I save, it actually works because this method is
already implemented in the controller.
So if I look at the implementation of this, on the
scope we're just saying remaining is this function,
and the function contains all information necessary for
calculating how many tasks are done and how
many are still remaining.
To calculate that information, I'm just going to use reduce
function, which is a native method that is available in
[INAUDIBLE]
compatible browsers.
So on the modern browser, this is a native API.
A legacy browser, you'd probably use a polyfill to add
this to the browser.
And what the function does, it just iterates over the array,
checks off all items that are done, and then increases the
counter if we find a task that is done.
And at the end it just returns the count of items.
That's perfect.
But what about me changing the status.
So if I check or uncheck one of the tasks, you see that the
remaining is automatically being recalculated and
updating the DOM for me.
So that's very nice.
I didn't have to do much to get that going.
So we have this link here called Archive, and what we
wanted to do is when I click on the link, I want to remove
all the tasks that are already done.
So to do that, I'm just going to use ng-click, which is
another directive that Angular templating
language comes with.
And I'm going to call up Archive Methods in our
controller.
So whenever I click on the link, it will actually go to
the controller and invoke that method.
And if you look at the implementation of that, we'll
see that it's, again, very simple, plain old JavaScript
recalling filter and other [INAUDIBLE]
method on the array.
That will just iterate over the array and create a new
array containing only those elements that
are not done yet.
And when we get this new array, we are just going to
override the existing array in items and scope items.
There's nothing Angular specific here.
And that's great because not only the controller doesn't
know anything about the view, about the presentation, it's
not doing any kind of DOM manipulation.
It's not even calling Angular APIs.
So it's super easy to test.
It's super easy to maintain.
And as you start building applications, you'll realize
that this is a very nice way of separating components.
The controller doesn't know anything about the view.
It's super easy to test the controller or reuse it in
another contexts.

So just to double check, yeah, the Archive link is working.
So how about adding a new task into the list?
Right now if I try to type something and hit the Add
button, nothing happens.
So let's implement that.
We have this form down here, and what I want to say is this
input field should be bound to something.
So I'm just going to pick ng-model.
It's another directive that creates two-way data binding
between the input [INAUDIBLE]
form control and the model.
And I'm going to bind it to newitem.text.
New item is just an object that is going to be created
for this form.
And we're going to bind directly to its text property.
So when I actually data bind it to that property, as I
start typing into the input box, the binding down here
will automatically update and I see the current value of the
input box there.
So we have that data bound, but in order for us to add the
new item into the array, we need to call some controller
method and provide the logic.
So I'm just going to call Add Method, and I'm going to parse
in the new item.

Perfect.
And now new task--
done.
It's working.
Perfect.
So when we look at the controller again, we'll see a
very simple function which takes the new item.
It will construct a new item with the text property set to
the text property of the form model and the DOM property to
set to false by default.
We're going to take this plain old object and we're going to
push it into a native array using the Push function.
And we're going to clear the text property of the form
model by setting it to empty string.
So what we get out of that is if you type something here in
New Tasks [INAUDIBLE]
and I hit Enter, it will push the new item into the
collection and it will clear the input.
That's super simple.
But if I have an [? entry ?] box that is empty and I hit
Enter, you see that I'm adding empty tasks into the list, and
that's not what I want.
I would like to disable the functionality if there's
nothing in the input box.
The way to do that, I could just use ng-disabled
directive, and ng-disabled takes that expression.
And if that expression evaluates to true, then the
current element is going to be disabled.
So the expression in my case is newitem.text is empty.
And to do empty I'm just going to use negation, so it's going
to be just [? false ?]
value.
OK.
The bottom is disabled by default.
So I start typing, new task, it's enabled, and it's
disabled because it's empty again.
Perfect.
This is working.
How about making this a little more complicated by saying
that we can only take tasks that are 15 characters long?
How would we do that?
So HTML already has facilities to do that, and we just use
max length set to 15.
And now I start typing and I say, my super long task--
[INAUDIBLE]--
I can't type anymore.
Well, unfortunately, this is how HTML works.
And it's not very user friendly.
We could do something better.
How about we write the max length to ng max length.
This is part of our form validation framework.
And what it allows us to do is if I start typing, my new
super long task, the input box will become red.
Now, if you look at the CSS and also the element, you'll
notice that the element now has a class called ng-invalid.
And if you look at the CSS, the CSS says that if there is
an input field with ng-invalid class on it, we're just going
to render a red border around this element.
So that's how the red appears.
And again, if we make it shorter, the validation
constraints are just--
[INAUDIBLE] the input is valid, and the class is
removed so we can remove the border and that happens
automatically.

Unfortunately, there's one problem with this application.
We not telling the user what's wrong.
We're just telling it that this input field is wrong, so
we want to display some text, some error message.
So let's do that.
So I'm just going to create a [INAUDIBLE] and I'm just going
to say, item too long.
And save it.
You see, oh, item too long.
But now there's nothing in the list, and we don't want to
display it all the time.
We want to conditionally display it.
So to conditionally display things in Angular, we just use
the ng-show directive.
And ng-show directive takes an expression, which, when this
expression evaluates to true, then the entire element is
going to be visible.
If it evaluates to false, it's going to be invisible.
And in order for us to write this expression, we actually
have to provide some names for the form so that we can data
bind to the validation model of this form.
So let's just call this form something.
Like New Item Form.
And this input box, we're going to give it
the name Menu Item.
So now what I can do is I can say new item
form dot new item.
Bind to the error model of this, and specifically, the
maximum length.
OK.
So it disappeared.
And I'll start typing my super long task.
You see that CSS kicked in, but also
the message is visible.
Now to start thinking about how would you do this without
data binding, what you would have to do, you would have to
listen on the input change.
So on all the keystrokes, you will have to do the
validation.
You would have to conditionally display and hide
the messages.
There would be a lot of work that you would have to do.
But because of data binding and the declarative nature of
data binding, it's super simple.
Just by adding two attributes, or actually one attribute
here, and one attribute to specify the validation
constraints, you can just get this done very easily.

So we have a very simple application going.
And if I try to add a lot of tasks, and I refresh this
page, everything resets.
The reason why it resets--
yeah, OK.
The reason why it resets is the persistence.
There's no persistence in this application.
And Vojta is going to show us how this persistence works and
how Dependency Injection, another feature that we added
to Angular, and something else that makes the existing
browser smarter, can help you with implementing persistence
in this application.
Do you want to start now?
VOJTA JINA: Yeah.
Maybe a little short break [INAUDIBLE].
IGOR MINAR: Sure.
We're going to take a short break.
I'm happy to answer questions if you have questions.
So if you've got questions, go to the
microphone and ask questions.
And Vojta is going to get ready in the meantime, and
then we're going to continue with the resistance and
Dependency Injection.

[SIDE CONVERSATION]
VOJTA JINA: So I need cable.

BRIAN GREEN: So you use this guy?
No.

IGOR MINAR: That's right.
Yeah, just point this in.

VOJTA JINA: Sorry for interrupting, but I think it's
good if we do this rather than if you did the same thing and
the [INAUDIBLE].

[END SIDE CONVERSATION]
IGOR MINAR: So anybody have any questions?
I showed you a lot of stuff.
I showed you the data binding.
I showed you form validation.
There are other things like routing that I
didn't even get to.
MALE SPEAKER: I have a question just about--
you mentioned jQuery.
Have you tested it alongside jQuery?
No problems?
Or are there some conflicts?
IGOR MINAR: There are no problems.
In fact, you can use jQuery and Angular together.
The way we implemented this is if a jQuery is present on the
current page, we're actually going to use jQuery for all of
our DOM manipulation.
If jQuery is not present, we have a tiny subset of jQuery
which we reimplemented, and we're
going to use that instead.
There are many people who are integrating Angular with the
jQuery UI widgets.
So if you have [INAUDIBLE]
or any of the other existing widgets, you can integrate
them with Angular.
And there are APIs to do this integration.
MALE SPEAKER: Very cool.
Thank you.
MALE SPEAKER: I have a question about the air
handling, is there a way to have it a dynamic air handling
instead of the declarative max length?
Can you add custom or more complex [INAUDIBLE]?
IGOR MINAR: You can--
so one thing about Angular is that we tried to make
everything extensible.
So not only--
I showed you the ng-repeat and ng-show.
All of these things we call directives are implemented on
top of APIs that we expose.
So you can implement all of them in your own way if you
find that whatever we provide is not suitable.
The same thing applies to validation.
It's completely customizable.
If you want to have your own validation rules, there are
APIs you can use to hook into the validation system and just
do your own validation.
MALE SPEAKER: OK, cool.
Thanks.

MALE SPEAKER: Yeah, can you use the data binding to set
CSS values?
IGOR MINAR: Yes.
I didn't show that, but you can totally bind to any text
or text value or attribute anywhere in the DOM.
And actually, you can even data bind to SVG elements or
XML if it's embedded in the document.
MALE SPEAKER: Cool.
Can you do also any sorts of math inside there?
Like any [INAUDIBLE]--
IGOR MINAR: Yeah.
So again, I didn't have any time for that.
MALE SPEAKER: Yeah, you're leaving out
all the good stuff.
IGOR MINAR: The expression language is quite flexible.
It allows you to do string concatenation, mathematical
operations.
But, intentionally, we are trying to make it--
it's flexible but limiting at the same time.
Because we don't want you to put too much
logic in the template.
The business logic should live in the controller, and the
expressions in the templates should just hook into the
controller and call the business logic in the
controller.
Because by doing that, the business logic remains in the
controller, and it's easy to test there.

MALE SPEAKER: Hi.
You were just using the Python Simple HTP server, but the
page was reloading as soon as you saved the change.
What was up with that?
IGOR MINAR: Library load.
It's an extension for Chrome.
You can just install it.
Yeah, Google Library Loads.

MALE SPEAKER: One question I had is--
IE implemented a lot of these types of features--
data binding--
earlier.
How are you going to get adoption in other browsers
with these features?
IGOR MINAR: How do we get adoption?
MALE SPEAKER: Yeah.
Because you said some of this right now is JavaScripted in
DOM, but you want to make some of the more advanced features,
the web components, to actually be, would have to be
implemented by the browsers themselves directly.
And how are you going to do that?
IGOR MINAR: How do we get other browser vendors to
implement it?
MALE SPEAKER: Yeah.
IGOR MINAR: Well, first we need a spec that is awesome.
And we need to show them that there are huge performance and
also productivity benefits to using data binding.
And we see it every day-- people, as soon as they start
using data binding, they're like, how did I build
applications before?
So once we have the spec ready, then that I don't think
we'll have such a hard time convincing other browser
vendors to implement this.
[SIDE CONVERSATION]
[INAUDIBLE]
IGOR MINAR: All ready?

[INAUDIBLE] to do that.
[INAUDIBLE].

[INAUDIBLE] let's talk about what [INAUDIBLE].
Do you know what I mean?
VOJTA JINA: I'm not sure.
IGOR MINAR: [INAUDIBLE].
VOJTA JINA: [INAUDIBLE] get it [INAUDIBLE].
IGOR MINAR: [INAUDIBLE].
VOJTA JINA: I know.
I will do something.
IGOR MINAR: [INAUDIBLE].
VOJTA JINA: I need to press this guy.
OK, cool.
IGOR MINAR: OK, guys.
We are ready to continue with the second part of the
presentation.

And we're going to talk about dependency injection and how
dependency injection makes Angular applications easy to
test and easy to structure.

I think we can start.
VOJTA JINA: Thanks, Igor.
Hey guys, my name is Vojta, and I work with these crazy
guys on AngularJS.
And today I'd like to show you dependency injection, which is
a really important part of Angular.
It does a lot of magic.
So first let me explain what is dependency injection.

[AUDIO PLAYBACK]
-Dependency injection.
Dependency injection [? being ?] object oriented
computer programming is a design patterned with a core
principle of separating behavior from dependency
resolution.
[END AUDIO PLAYBACK]
VOJTA JINA: See.
That simple, it is.

All right, thanks for watching, guys.
[LAUGHTER]
VOJTA JINA: No, seriously.
Why should you care about dependency injection?
I mean, what are the benefits that you can
get from using it?
Well, it will help you to write code that is easy to
maintain, and as a result of that, you will be more
productive.
And that's something you should
definitely care about, right?
Being more productive, that sounds good.
But how is this thing going to make me more productive?
I mean, is it going to stop me watching YouTube?
Not really.
It's not that cool.
But less code.
I mean, usually, when you write an application, you
write these small units and each of those units takes care
of part of the functionality of the whole system.
And then you need to wire all these units together.
And that's exactly what dependency
injection does for you--
it wires all these things together automatically.
And by the way less code, that doesn't mean just less typing,
but that's less reading, less code to understand, less code
to refactor.

Next, it'll help you to write code that is easier to extend.
So anything like adding new objects, adding new
[? dependencies ?]
into your system, or refactoring your current
architecture, just rewiring the structure somehow.
Or things like having different instrumentation in
different environments.
For instance, you want to do some debugging instrumentation
during development, but you don't want to do that in
production.
All these tasks are way easier to do with dependency
injection because the whole system is more flexible.
And the last thing, my favorite one, it
is easier to test.
All right, try to remember these things because now I
would like to do some real concrete examples of these
benefits, how this flexible system will help you.
And I want to show you how easy it is to do testing with
Angular and dependency injection.
All right, so let's do coding.
This is going to be a surprise, but guess what?
I did the same application as Igor.
Basically, Angular is really cool if you want to
build a Todo app.
It really rocks.
So I don't have to explain this app because Igor already
did that, and I'm basically roughly at the same stage as
when he ended.
So the app is cool, but if I do some changes, like removing
these two items, and I refresh, I get the same items
again because it's hard-coded in the controller.
And there's no storage, nothing like that.
So what I'm going to do, I'm going to
create persistence storage.
I'm going to use MongoLab, which is really awesome
storage in the cloud.
They basically provide you MongoDB plus RESTful API.
So I already created an account, and we're
going to use that.
Let me show you the code.
Here's the template.
And here's the controller.
And of course, we have our unit test, as well.
So now my idea is I would like to obstruct this whole logic.
All this stuff is really through MongoLab.
I would like to abstract that into separate objects.
In Angular we call it service, so let's call
it service for now.
And this service will be responsible for sending all
the requests, setting proper headers, parsing the response,
and all this stuff related to MongoLab.
You can think about it as a model.
So let's call it item resource.
And we're going to replace these static hard-coded items
with, say, item dot query, or something.
And this call will basically fetch the data from MongoLab.
All right.
So far, so good.
But here's the first problem.
Where do I get this item object?
I mean, the first thing I can do is just
instantiate it on my own.
So I can do item equals new resource item, or something.
And it's going to parse the response.
So let's say it requires some JSON parser,
and maybe some XHR.
[INAUDIBLE]
basically to send the actual request.
All right.
This looks good.
I mean, I think this would work.

Can you see anything bad to this?
I mean, come on, it's just one line of code.
Is there anything suspicious?
Or?
OK, so the first thing I don't like about it, the first
issue, is that this controller knows too much.
This controller needs to know what is the constructor of
this item, its resource item, and it needs to know how to
instantiate this, this constructor.
So the whole idea of abstracting and encapsulating
all this logic into separate objects to make it nice and
easy to understand is kind of broken.
Because now this controller needs to know how to
instantiate this thing, so all this information is kind of
leaking into this controller.
And as a result of that, it is really difficult to
maintain this code.
Because if I for some reason decide to change JSON to XML,
I need to go through all the controllers that are using
this resource item and I need to change
this into XML parser.
And this controller really doesn't care about that.
This controller doesn't consume XML or JSON, so it
should not be aware of that.
So that's my first issue with that.
How about testing?
How about test this, guys?
Brian, could you actually bring me something to drink?
Thank you.
How would you test this?
MALE SPEAKER: [INAUDIBLE].
VOJTA JINA: I'm sorry?
MALE SPEAKER: Multi-batching.
VOJTA JINA: Yes.
So basically, it would be possible.
It would be really difficult, but it would be possible.
Because the resource item in this constructor is defined on
Windows objects, so you could [INAUDIBLE] that.
But the trouble with that, it is a lot of hard work.
And you need to be careful about cleaning.
You need to clean up after every test.
Because otherwise, you will have these conflicts where one
test looks like the other unit test, and it's kind
of tricky to debug.
And I don't like that.
It's really difficult to test that code.
So as a result of that, no one will test that.
That's the trouble.
All right.
One more thing I don't like about this code, and it's
something we call hidden dependencies.
Because basically, this constructor is lying to you.
Because if you want to instantiate this controller to
stand alone and you look into this constructor and you see,
oh, it requires a scope, sounds good.
But then you try and instantiate it, and in the
background it will create a resource item and try to fetch
data from the server.
And it's really bad even for understanding the code.
Because you look into this constructor, and you see, OK,
it needs scope.
But then you need to read the whole constructor to actually
see all the real dependencies.
So hidden dependencies, another issue.

OK.
Let's make it better.
Lets us something that is called factory.
So we define this object and [INAUDIBLE]
get the resource item.
And this function is going to return just a new instance of
resource item.
And it will pass in terms of its parser and XHR.
So we need these [? methods ?] as well.
Get parser.

And get XHR.

Now we can change this line to call factory [? instat. ?]

And it is a lot of code, but it turns out that this is way
better than the previous one.
Because this actually solves a lot of issues.
For instance, the first thing is now we just separated the
behavior, which is in the controller, from dependency
resolution, which is in the factory.
So now, if you decide to change a JSON parser to XML
parser, it's easy.
There is just one place to do that in this factory.

Another good thing is now the controller doesn't need to
know how to instantiate this service.
It still needs to know where to find it.
It needs to know that this factory [INAUDIBLE]
is [INAUDIBLE], which is still not good, but at least it's
not transitive.
So it needs to know where to find its direct dependencies.
So that's better, as well.

We still have hidden dependencies.
That's still the same.
How about testing this code?
How would you test this code?

Any ideas?
Come on guys, I'm pretty sure you know how to test that.
MALE SPEAKER: Mark object.
VOJTA JINA: Mark object.
OK, I'm not sure what you mean with that.
MALE SPEAKER: [INAUDIBLE].
VOJTA JINA: Yes.
Yes.
That's definitely the way to go.
So again, we would [INAUDIBLE]
the factory.
So basically, it looks a little bit less ugly, but it's
completely the same thing that we were doing with the
previous example.
We need to [INAUDIBLE]
this global state, which is the factory.
So again, we have the same issues with cleaning up.
So again, for me, this is difficult to test.

All right.
Let's use dependency injection, then.
Let's use this Hollywood princip which
says, don't call us--
we'll call you.
And check out this guys.
This is my favorite refactoring.
You take this factory, you just remove it, and you take
this line, and you remove it.
And instead, you just ask for this dependency in the
constructor.
And that's all.
You're done.
And it turns out that this actually solves all the issues
that we just discussed.
We still have the separation of behavior in dependency
resolution.
There's no hidden dependency.
So you look into this constructor and you can
exactly see what are the dependencies, so it can help
you as a documentation as well.
And the best thing-- this controller has no idea how to
construct this item or where to get.
It will just get it parsed in.

And dependency injection will take care of that.
All right.
I can show you the app that it really works.
Now if I refresh the page, you can see there's a request to
MongoLab, and I'm getting these items from the server.

OK.
Do you have any questions to that?
FEMALE SPEAKER: [INAUDIBLE].
VOJTA JINA: Wasn't that funny?
I'm glad for that.

MALE SPEAKER: Where do you pass in the item?
VOJTA JINA: That's a good question.
That's magic.
I will show you in a second.
Any other questions?
OK.
Let's move on.
So these were kind of the general ideas behind
dependency injection.
I mean, I would say problems that
dependency injection solves.
And that's something you can apply
pretty much to any language.
So now let's go a little bit more into Angular world and
see how it goes in Angular.
MALE SPEAKER: What about the main method?
VOJTA JINA: Main method?
MALE SPEAKER: Yeah.
Where's the main method in this application?
VOJTA JINA: It's hidden.
Mishka would say there is no hidden method, but I mean, I
think it's something I can explain in a second, as well.
MALE SPEAKER: OK.
Just don't forget.
VOJTA JINA: OK.
You can remind me if I do forget.
MALE SPEAKER: I will remind you.
VOJTA JINA: I know.
I know you will.

So we know how to ask for things.
That's easy.
You just add an argument into a constructor and
you will get it.
Because Angular, whenever Angular needs to instantiate
anything like controller, directive, or anything, it'll
ask Injector to do that.
So that's easy.
But the question is, how does Injector know what to inject?
That's exactly your question.
And the answer to this question is modules.
So basically, an Angular module is nothing more than
just a set of definitions.
So in this case, we are creating one module that is
called Todo.
And then we are adding first a definition--
how to construct App Controller.
It's basically Constructor, right?
And another definition is here where we are saying, this is
how to create item service.
So again, it's sort of Constructor.

And then where we are coming to the main method, to the
hidden main method.
Because when Angular is starting the application, the
first thing it does, it creates an injector.
It creates an injector and it loads specific modules.

And you can specify these modules in HTML and ng-app.
This is basically where we are saying ng-app equals Todo, so
that means this is the root element of my app, and Todo is
the module that I want you to load.
So in the main method, which is actually registered as a
listener on document content loaded--
so when the page is loaded--
Angular will call this main method.
And this main method will create a new injector and load
this module.
And then the entire system, any unit from this whole
system, can ask for anything that was provided before,
like, by loading some module.
So in order to ask for something, anything you want
to ask for, you need to provide that
first through modules.
Does that make sense?

OK.
So we know how to ask for things.
Just adding arguments through Constructor.
And we know how to provide things.
Through modules.
We basically create modules, which is a set of definitions,
and then we configure the injector with these modules.
Simple.
Now let's see some more interesting stuff that you can
do with all of this flexibility.
In Angular, whenever there is an error, Angular always
delegates exception handling to a service that is called
Exception Handler.
Let's see how this works.
Let's do throw new error--
some error.
And now if I try to add an item, I will get this error.
Nothing super cool, right?
But the thing is--
MALE SPEAKER: [INAUDIBLE]?
VOJTA JINA: Well, because the default implementation of
Exception Handler will just dump it into [? console, ?]
right?
But with dependency injection, I can easily provide a
different version.
So I can say hey, injector, use this version of Exception
Handler, and this one will just alert.

And now if I do the same thing again, there you go.
We have [INAUDIBLE] instead of dumping it into [? console. ?]
And if you think about this, we just changed the behavior
of the entire system.
Because now when there's any exception inside Angular or
whenever, it will always be delegated to [? OERT ?]
instead of dumping to console.
So it is super easy to do things like I mean, during
development, you probably want a server exception.
But in production you maybe don't want to do that, and
instead, you want to send an error report to your server in
the background or something.
And dependency injection gives you the sort of flexibility to
do that easily.

FEMALE SPEAKER: [INAUDIBLE]?

VOJTA JINA: Sure.
You mean this?
FEMALE SPEAKER: Yes.

VOJTA JINA: OK.
One more example of this flexibility.
Let me remove this error first.
This is the item service that is responsible for all those
other communications in MongoLab.
And there is something called API Key, which is basically a
sort of authentication with MongoLab.
And it is hard coded.
So let's say that now I decide to refactor that.
I decided that I needed to have a different API key for
development and a different API key for production.
So this kind of refactoring is easy because I just take out
this string, and instead of hard coding it, I'll
just ask for it.
And I will provide this value.

And I can provide a different value in production, or
whatever your environment is.
And for me, this is really important.
For instance, the last two or three weeks I've been working
on TextDrive, which is a text editor for Chromebook.
And I was basically working, I was using really unstable APIs
because the Chrome guys, they were working on that.
So basically, I did something one day, and the other day it
was completely broken because they changed the API.
So I had to change my architecture and everything.
And guess what?
The very next day it was broken again because of some
other changes.
So result of that is that your awesome architecture that you
originally designed suddenly is not that awesome-- it
doesn't fit the current state.
And I strongly believe that the only way to keep this
fresh, keep it nice and clean and readable, is just to keep
refactoring.
And that was exactly the point when I realized, oh my God,
this dependency injection stuff is awesome because I can
easily rewire all the stuff--
I can just say now this service, it makes really no
sense to do that inside this service, so I'll move this
function through another service--
and it's a piece of cake.
It's just so easy to do that.
And the thing is that you only do these things if it is easy.
If it was difficult for me, this kind of refactoring, I
would be like, yeah, it works, so I can live with that.
So if that's the reason why it's important to have these
operations to be easy, because then you do them.
OK, last thing, I think that's the best example of how
flexible this whole system is.
It's an extension that we have.
It's called [? Baterang, ?]
and it's something that Brian [? Ford ?] did.
And I think Brian might show us how this works and how
awesome it is.
And how important dependency injection was in order to make
this happen.

[INTERPOSING VOICES]
BRIAN GREEN: Do you have it up there?
IGOR: Which way do I go?
BRIAN GREEN: All right.
So, [? Batarang ?] is the name for our debug extension for
Chrome, because Angular Debug Extension for Chrome is a
really boring name.
MALE SPEAKER: [INAUDIBLE].
BRIAN GREEN: All right, this works.
OK.
Anyway, it hooks right into the Chrome Developer Tools,
and is uses some cool features of dependency injection to let
us see things about our application.
So one cool thing that it does is, you remember that scope
object before?
So in addition to just requesting objects, you can
also, once an object has been registered into the dependency
injection system, you can ask for it, make some changes to
it, and then pass it along.
And that object is changed then state-wide.
So one of the things that we were able to do was we were
able to keep track of all of the models attached to all the
scopes in the application and then build up this
visualization here.
So you can modify some of this stuff.

And you see it's updated in the application up here.
So there's also some cool things that you can do to
measure the performance of your application.
Again, the basic strategy is--
you have the natural scrolling-- this
is throwing me off.

All right.
You can kind of see it on the side there.
Is there a way for me to change the size of this?
MALE SPEAKER: [INAUDIBLE].

BRIAN GREEN: Oh, here.
I think you need to pop the window out.

All right, there you go.
That's a little bit better.
OK.
So the basic strategy here is around when Angular is
watching your different models for changes, typically it
would be really annoying to go through and try and profile
your entire application.
But with dependency injection, we can say give me this
function, I'm going to wrap start timer, regular function,
stop timer, pass that back into the system, and now you
can profile all these different things with just a
few lines of code.
And I'm not sure.
Does anyone have a great idea of how you do that otherwise?
I mean, the only other thing I've seen in your typical
import kind of system is you have to manually wrap around
all these things.
It's really frustrating and difficult to try and add
profiling to your entire application.
So there's lots of other cool tricks that you can do, as
well, but these are just some examples.
Any questions?

MALE SPEAKER: Where can I get [INAUDIBLE]?
BRIAN GREEN: That's a good question.
VOJTA JINA: [INAUDIBLE] always has good questions.
BRIAN GREEN: Yeah, you are full of good questions.
So if you check out the Angular blog, underneath here
we have a post on that I just [INAUDIBLE].
VOJTA JINA: [INAUDIBLE].
BRIAN GREEN: I know.
Your scrolling is really confusing to me.

VOJTA JINA: [INAUDIBLE].
BRIAN GREEN: And yeah, your window is also
kind of sized weird.
Can you fix it?

There we go.
That's what [INAUDIBLE].
Yeah.
So there's instructions here.
I'm getting it.
Right now you need to use Chrome Canary because we're
using some cool new features that are like really bleeding
edge in Canary.
They'll reach the state of Google Chrome soon, and then
we'll be able to put this in the web store and it'll be
super easy.
But if you're interested in it now, there are instructions.
You'll have to enable some flags and stuff, but then
you're good to go.
VOJTA JINA: Cool.

Thanks a lot, Brian.
BRIAN GREEN: Yeah, no problem.
VOJTA JINA: That's awesome.

It's awesome stuff.
I mean, this guy's awesome, as well.

OK.
I think I mentioned testing so many times, so let's see some
cool examples of how can Angular make
easier the whole testing.

Let me do this first.

All right.
So here's our unit test.
I was originally parsing, but now we did
this thing with MongoLab.
So let me execute these tests.

Yeah.
If you want to complain about the name of this project,
somewhere in the back there is Mishka.
He is the author of the name.
Just so that you know.

IGOR: So what is this spectacular
thing we are using?
I heard something about it being a
spectacular test runner?
VOJTA JINA: Yeah, that's exactly what it is.

Yeah, so Testacular is a test runner to execute your unit
tests on real browsers or real devices.
So now I'm going to run all these unit tests on Chrome,
but you can run it on a phone or whatever you want directly
from command line or your ID.
And it can watch all the files as well and automatically run
the tests-- that's something that I'm going to use now.
So you can see if I can save the file it will immediately
execute all the tests.
Can see that now these tests are failing.
And the reason why they are failing, it's complaining that
unexpected request [INAUDIBLE] to blah, blah, blah.
And the reason for that--
IGOR: Sorry.
What is this describe and [? edge ?] stuff?
VOJTA JINA: Ah, sorry.
I forgot to mention that.
So these units, as some of you probably already know, it's
written in Jasmin, which is a really awesome testing
framework that we really like.
But honestly, you can use any testing framework you like.
But with Jasmin, Angular gives you some helpers to make the
whole testing even more easier.
So for instance, the first helper function is this module
function, which basically helps you to load the module
during your unit test.
Because what happens in the background, for [? every ?]
pack, we create a fresh, new injector.
So you don't have to worry about any cleaning because
every unit [INAUDIBLE] gets a whole fresh, new environment
with a new injector.
And this module function, that's just
for loading a module.
So you can see before each spec, I'm loading this Todo
module, which is basically my app.
So in order to test it, I need to load it.
All right.
Now these tests are failing because
it's an expected request.
And the reason for that is if we go back to the controller,
here's the source of trouble--
item query.
This guy tries to send XHR reverse to server, and that's
something we don't want to do.
Ideally, I would like to test this controller ignoring all
the server side communication, just test the logic in this
controller.
And it turns out that with dependency injection, you can
do that really easily.
Because what I can do, I can use different implementation
of this resource item.
So I already wrote this mock version, and this mock is
something we call--
it has the same API as the original
service, but it does nothing.
It just pretends to send a request to the server, but
actually it does nothing.
These are just empty functions.
And I'm putting this and registering that into mock dot
item module so that I can use it during testing.
So now if I go back to the unit test and I load this mock
module, as well--
so I do mock dot item--
and again, I save the file, it immediately executes all these
Todo tests and now they are passing.
And why they are passing?
Well, because in the controller now this item is
not the real one.
The controller has no idea what it is because it has the
same API, the same method, so it doesn't complain.
By during this unit test I'm injecting this mock version,
the fake version of this item, and this one doesn't do any
XHRs at all.
Instead, it just returns empty array.
This map, it returns an empty array.
And this guy, like item dollar-save, it's just an
empty function, it does nothing.
So I can focus on my logic in the controller and just ignore
the whole server side business.

Does it make sense?

All right.
MALE SPEAKER: Can you go back to the declaration of
[INAUDIBLE]?
VOJTA JINA: Yes.
So you can see is just an empty object
with these two methods.
And I said they were empty functions, but actually I'm
using Jasmin's [? PI, ?]
which is something so that I can assert whether it was
called or not.
But it does nothing.
So you can think about it as an empty function.
MALE SPEAKER: Where do you register the mock item as the
item [INAUDIBLE]?
VOJTA JINA: Because here I'm creating another module, and
this module is not loaded during production.
But during my unit test, this one, I'm loading
this module, as well.

Yes?
MALE SPEAKER: Could you explain the Angular
[INAUDIBLE]?
VOJTA JINA: Mm-hm.
MALE SPEAKER: So you have [INAUDIBLE] called exit
module, [INAUDIBLE] the name, and then the data, and then
dot value the item module.
VOJTA JINA: Yeah, let's make it more explicit.
So this first line creates a module, and then I add this
definition to the module.
That's the same thing that I was doing before, but I guess
this is easier to understand.
I'm sorry.
MALE SPEAKER: It's all right.
VOJTA JINA: Cool.
IGOR: So the production code used module dot factory, but
the test code uses module dot value.
What's the difference?
VOJTA JINA: Igor.
Again.
[LAUGHTER]
VOJTA JINA: You always ask me these questions.

Well, OK, I will try to explain that.
IGOR: Sorry.
I don't mean to bother you.
VOJTA JINA: That's OK.
I still love you.

So that's a good question.

This guy used factory to register to add this
definition into the module.
And when I was doing the previous one with the
Exception Handler, I was actually using value.
This is something that I was doing, I believe.
And there is a bunch of other methods, as well, but they're
basically just different ways of doing the same thing.
So they all do the same thing.
They register this definition, they tell Injector how to
construct something.
And the only difference is the value actually registers a
concrete instance.
So this function is the actual instance that will be injected
into the whole system.
But factory, that's a function that will be called in order
to create the instance.
So this function will get called once, and as a result
it returns to instance.
And that's the instance then will be passed around in your
application.
So basically, this Exception Handler, I could change that
into factory and I would do function, return function, and
this would do the same as the value.
Does it make sense?
But the thing is that in this function, I
don't need any injection.
I don't need to inject any argument, so I can just define
it as a value.
That's why I decided to use value.
But this is the same.
It's just different syntax.
MALE SPEAKER: [INAUDIBLE]?
VOJTA JINA: Yes.
Now I can inject something into this factory function.
So I can ask [? Dollarvendo ?]
and I can [? Dollarvendo ?]
[INAUDIBLE] instead.
IGOR: [? Dollarvendo ?] is just a service that provides
the window of the [INAUDIBLE].
VOJTA JINA: It's just a wrapper around the browser's
window so that you can pass some mocks in testing.

All right.
Let's go back to testing.
One more thing I want to show you.
We just ignored completely the whole
communication with MongoLab.
And you might point out, that's something you want to
test, as well.
Yes, I want to be sure that the correct requests are sent
and that my controller and my whole app works with the data
that I get back from MongoLab.
So yes, I can do that.
I already wrote unit tests for that.

Where was that?
This guy.
And I think this is a good time to explain the other
helper functions that we provide you to make testing
with Jasmin easier.
And this function is Inject.
Because I told you that every task has a fresh new injector.
And this inject function basically gives you the same
luxury of just asking for stuff as you have in the
production code.
So if you're defining a controller directive or
something, you can just ask for things and
you will get it.
And if you use this inject function in the unit test, you
will get the same luxury.
So this inject function basically delegates, it
invokes the given function through Injector.
So Injector takes care of instantiating all the
dependencies and all that stuff.
So the result is that I can easily ask for any service.
I can ask for Dollar Controller, Root Scope, Dollar
HTTP back end, and I will just get it.
I don't have to instantiate them, I don't have
to look them up.
IGOR: How does Angular know what to inject?
VOJTA JINA: Well, it's based on what you provide with these
modules, and it's based on the string names.
So if I go back to my controller, this controller is
asking for a scope and asking for an item.
And these names, they need to match.
So you're asking for item, and here, down here, I'm
providing this item.
And these strings are exactly the same.
That's how Injector knows what I want to inject.
So in a different word, the order of these arguments
doesn't really matter.
I can change that and it's still going to work the same.
Because the order of the arguments
doesn't really matter.
Because this function is injected.
So it looks-- the name of document, based on the name of
the argument, it will inject the correct instance.

MALE SPEAKER: [INAUDIBLE]?
VOJTA JINA: I'm sorry?
Say again.
MALE SPEAKER: [INAUDIBLE]?
VOJTA JINA: Of course.
And modules can depend on each other.
MALE SPEAKER: Why [INAUDIBLE]?
VOJTA JINA: I'm sorry.
To repeat the question, the question was can we load
multiple modules ?
And the answer is yes, you can have structure.
Like one module can depend on another module.
MALE SPEAKER: [INAUDIBLE].

MALE SPEAKER: [INAUDIBLE]
item?
VOJTA JINA: Then it's overridden.
Just the last one wins.

OK.
Let me finish this thing.
And that's this guy.
So you can ask for things during unit tests, as well.
That's cool.
And another cool thing about Angular is this
HTP back end stuff.
Because in the previous example I mocked out
completely the service, so it was just a
set of empty functions.
But that means you have to write mock for
every extended service.
And it turns out that Angular has something that's called
HTTP Service, and this service is responsible for all the low
level stuff.
It sends all the requests.
So even my item resource, at the end of the day, it sends
the request through HTTP.
So Angular provides us a mock version of this HTTP service,
and that's what we are using here.
So this HTTP service, it's not the real one.
It's a mock version.
It's fake service that just pretends to send requests, but
it doesn't send them.
It just pretends them, and then responds
with some fake data.
And in addition to that, it has some more APIs suitable
for testing.
So this guy has method expect get, and you can basically
train this mock HTTP back end.
You are training it like, hey, expect guest requests to this
URL, and then respond to this fake data.
And these data are defined right here.
And you can see that it's basically
dumped data from MongoLab.
So I can assert whether my controller works properly if
it's kind of real data without actually sending XHR requests
to your server.
So all these unit tests, there is nothing
expensive like that.
So you can execute tons of these unit tests in a matter
of seconds.

I always like to say that you should never trust any unit
test without seeing it fail.
So let me show you that this really works.
You can see we have now seven units, and let me show you--
this is a unit test for [? AdMethod. ?]
So it basically tests whether we send the
post request to MongoLab.

And it says expect post request to this URL and expect
these data.
So if we go to the controller to [? AdMethod, ?]
this item [? DollarSave, ?]
that's the guy who eventually triggers this request.
So if I [? comment out ?]
this guy and execute a test, you can see it's failed.
[? Answer ?] despite request.
Post to this URL.
Because it was expecting this request, but this request
never happens.

So let's fix that.
And last thing.

We are expecting these data, but I can change that to set
the test to something.
So now it's going to fail.
And you can see there is a different error.
Because now it says, hey, expected post request to this
URL with different data.
So it expected this request, but the data was different.
The expected text was fake to us, but it
actually got something.

With these mocks, you can actually unit test the whole
system, whether it works as expected, really cheaply
without doing any real XHRs.
Because you can just train this mock version of HTTP to
pretend to be your server.
And the rest of the system has no idea about that because the
APIs are the same.
And dependency injection, that's the guy who enables you
to do that.
OK.
Unless you have any questions, I think I'm done.
MALE SPEAKER: Scope is another [INAUDIBLE]
instance of the controller.

VOJTA JINA: Not really.
Controller is basically the creator
function that gets scope.
So controller basically publishes all the stuff that
it needs to be accessible in template, publish this stuff
onto scope.
IGOR: So the scope is like a context that is associated
with the controller.
MALE SPEAKER: Yeah.
So the scope basically says the context is shared with the
view [INAUDIBLE]
IGOR: Yes.
MALE SPEAKER: And where do we find out about all the
services that come wrapped up with Angular these days?
VOJTA JINA: You can search--
you can look up our documentation.
I think that's the best way.
IGOR: [? docs.angularjs.org ?]
We have a complete list of all the services available and
also examples of how you would use these services.
But as with what we showed, we provide you some services for
very basic stuff.
But as you start building applications, you'll see that
you want to build your own services.
Angular is not this constrained box that you get
what we provide you with.
We actually just provide you the minimum amount of APIs
that are necessary for very common tasks.
But we expect people to just build components that they'll
use and they'll extend Angular through dependency injection
or through other APIs.
The templating engine is completely
accessible, as well.
MALE SPEAKER: Another question.
Can you come to the mic, please.
MALE SPEAKER: So a little bit less of a question, more just
of a comment, maybe a discussion point.
So the dependency injection is super, super powerful.
Could you just go quickly back to the todo.js and go to the
place where you're binding the values to the app,
like the API key?
So one idea I was thinking--
and I don't know if you guys have considered this--
it seems to me it could be very powerful to be able to do
some of the dependency injection definitions,
particularly around the values, declaratively.
So for example, instead of saying todo dot value API key
is this string, to be able to have a JSON object that
declaratively defines all of these bindings.
And then maybe be able to take that JSON object and pull it
out of the actual code so that it's extrinsic.
So that you could maybe point to it and have it maybe at the
other end of a URL.
Or potentially even have it stored in a database where you
could kind of pull it out.
So the idea that the code is over here, the bindings of the
values are declaratively JSON--
VOJTA JINA: I think that's a good idea.
The only problem, trouble with the current implementation of
the injector would be that you need these values to get them
before you instantiate the injector.
So this is something we would have to solve.
But otherwise, I like that idea.
MALE SPEAKER: Yeah, I know.
I'd love to offline maybe discuss it.
Cool.
VOJTA JINA: Thanks.
So thank you very much, guys.
I think I'm done.
But I'm happy to discuss anything afterwards.
Thank you.
Thanks a lot for watching.