Angular: A Radically Different Way of Building AJAX Apps

Uploaded by GoogleTechTalks on 16.08.2010

HEVERY: So, welcome guys. My name is Misko Hevery. I work here at Google, and I always
try to come up with crazier and simpler ways of doing stuff. And one of the things I got
into recently is actually JavaScript. I've only been doing JavaScript for about two years
and, you know, that's how I kind of discovered node.js and then just how amazed I was by
it. But anyways, so on a client side, building web applications, building Ajax applications,
for those of you who have tried it, it's a real pain. How many of you guys have tried
building a web app? It is a real pain in the butt, isn't it? And so, you know, what people
end up doing is they create bunch of libraries to make your life easier, and I basically
kind of looked at it from a different point of view and said, "Can we build a web app
but just make our life easier?" Not because we have libraries to make our life easier,
but because browser is just smarter. And so, this is what I mean by--and when I say, it's
a radically different way of building Ajax applications. So, what is Angular? It's kind
of hard to explain and so I'm going to give it a try, but fundamentally, it's not a library.
It's not a library like jQuery or Closure for manipulating a DOM. It's not a library
like Closure or Dojo for having your widgets. It's not a framework like Sinatra where is
that, oh, if you play by our rules, we'll--you know, we have done all the hard work and you
just plug-in your individual pages here. I like to say, in libraries, you get to call
the library and in a framework, the framework calls you. Angular is neither of them. What
Angular is it's a smarter browser. Angular is what a browser would have been like if
it was specifically designed for building Ajax applications. Obviously, browsers are
not designed for building Ajax apps; they're designed for building--for showing static
documentation. So, Angular is to dynamic documents what HTML is to static documents. This slide
over here is going to make a lot more sense after I give the demo, but, you know, every
single kind of system has kind of a model view controller, and everybody says that it
has completely different meaning too if you talk to five different people. It will probably
have a different meaning in this world that I'm going to present. I just want to point
out that we do have a separation for the model view controller. What the view is in our system
is the pure HTML. What the model and the controller is, is JavaScript. Really, model is the JSON,
and the controller in our world is the JavaScript that you write. And there may be a couple
of services which is stuff that's useful for building web apps. But the key thing that
makes all of this thing possible is two-way data binding, and we'll talk about all this
stuff later in a second. So, really, the core of it is the two-way data binding. So let
me give you a demo. So as I said earlier, what we're going to end up building by end
of today is this Buzz client, but I'm going to start with a very, very simple demo and
that is this. So, here we go. So if I have a simple HTML like this, which I'm sure you've
seen before, and the really interesting part is this, you now have an input field that
says, "World" and would I want to say, "Hello, world" right here and what I really want to
say to the system is, "Look, take the input field over here and put it over here," right?
Now, if you open this up in a browser,
it looks like this and most importantly, it doesn't do anything, right? This is the standard
static document that we're all familiar with and it's all boring. So how can we teach a
browser new tricks? So we do this by including the Angular script tag inside of it. And again,
I want to point out that I'm not really teaching--I'm not really calling any code, right? I haven't
changed anything. I haven't written any extra code. The browser just became smarter all
of a sudden. So if I refresh my browser, all of a sudden, "World" gets copied down here.
And not only that, as I type, it immediately copies it over. This is what I mean by data
binding. It's literally moving the data over because I said that the name here and the
name there is one and the same thing. Okay, so how can you use data binding to do something
interesting? Well, let's see. Darn I forgot my cheat sheets. One second. My cheat sheet
is this. So, if you wanted to talk to Google Buzz, there's a particular URL we can hit
and the Google Buzz will give back our data. And so, now that--the hard part of building
a web application is how do I take this raw JSON data and present it to the user in some
kind of a form? So, how can we do this? Well, the first concept, what we have done here,
let's see. We--I've already included a script right here, which is empty. So I'm
going to declare a--my application, let's say, or buzzdemo. And one of the things we
want the buzzdemo to have is access to resources. And I'm sorry, this is kind of complicated,
so I'm going to have to copy it over.
And what this basically says is that, you know, if we go back to--here we go. You know,
see this complicated URL up here? It's JSON where this is where you drop the name, et
cetera. That URL is essentially this piece over here. It says, "Well, this is the URL
that you have and I want you to talk to this URL using the JSONP protocol," and a callback
for the JSONP is this thing. Are you familiar with JSONP? Folks, some of you guys maybe?
Okay, it's just a way of fetching the data from the client and most importantly, I'm
going to name this particular thing called activity, because that's what the Google Buzz
uses; they call that an activity, and I'm going to give it two methods called "get"
and "reply." So, if I say, "activity.get" it will take the "self" into visibility. So
this thing will become visibility, but if I say "replies" then the "self" will be dropped
over here, but furthermore, the "comments" will be dropped up here and then s user I.D.
and activity I.D. is what the user will have to supply. So basically, I'm building a kind
of a language for talking to JSON stream that Google Buzz provides. Okay, now, the other
part is we have--how many of you guys are familiar with Guice? All right, so we have
the penance injection in here and so we need to say we want to inject "resource" and that's
the "resource" here. Okay, now, this in itself won't do anything yet, but what we want to
do in our HTML is we want to say--actually, I want to put some behavior, some controller
behind this view because HTML is just a view. So I'm going to say, "controller" is equal
to "BuzzController." And inside of my buzz, I'm going to declare a controller, so I'm
going to say, "function BuzzController" and in here, I'm going to say, "Buzz prototype."
And let's make a method called "fetch"
and let's keep it simple here. I'm going to say, this dot--I think I called it--one second,
I called it activities, "this.activities=this.activity" This is the guy which we declared up here,
"get" that's this method down here and we want to call a "get on" user I.D. is "googlebuzz."
Right, and so in the constructor of this thing, we're going to say, "this.fetch." Okay, so
when the controller comes up, it's going to call the fetch method and the fetch method
will go and fetch all the activities for Google Buzz. Now, that is not going to do much yet,
so let's leap this demo over here and say, "preactivities" is equal to--and with a little
bit of luck--oops, I've made a mistake. All right, where did I make a mistake on? Oh,
I see. All right, I think this one, there you go. So what has just happened? What I
asked the system to do, if you look at our HTML, I simply said instantiate the BuzzController
in the controller's constructor we call the fetch method, and the fetch method--maybe
I should put this next to each other like this. The fetch method assigned all of the
activities from the JSONP into the activities variable and all I'm saying here is print
out the activities variable so that I can dump it out. And so, as you can see when I
refresh, there's a second one, the activities is empty and eventually, the data shows up
and draws what we have. Excellent. So, the next thing you'll probably want to do is just
fetch the data for different people, not just for us. So let me cheat a little bit here.
This ready? Okay, so let's do it "do" and say, "input, type, name, user I.D." and "button
fetch, click=fetch." Okay? So now, we're going to change the code a little bit. So instead
of doing it in a constructor, we're going to remove that and instead of just always
grabbing Google Buzz, we're going to grab "this.user I.D." That's the same user I.D.
that you see over here. So now, I'm going to refresh this and I'm going to say, "googlebuzz
fetch" and after a second, data comes and I can say, "fetch myself" and I get different
set of data for different people. So, so far, we're making some progress, right? I mean,
you can fetch our dataset and display it. So, the next thing we'd like to do is instead
of dumping the data in a row format, it'd be nice if you could somehow format it nice
and pretty. So, I'm just going to cheat a little bit here because I don't remember everything.
All right, so we're going to make a UL which is on our list and then we're going to say,
"li" and inside of the LI, let's say, if I go back over here, let's say I just--as you
can see, we have activities. Activities has data and the data has a collection of items
over here. And items, for example, has the text and the text is--let's see, items, actor--or
sort of--okay. So the actor is a person who did the activity and the "object.content"
has the particular things. What we want to do is we want to show the content for each
of the--each of the buzzes, right, that were done over there. So, we're going to say, "ngrepeat."
So, we want to repeat the LI element for each item in "" and what we
want to print in the middle of it is "item.object.content," right? Because once we find the items over
here, when we go to the "object.content," it will printout the content of it. So if
I save this and I do refresh and I do fetch, we have individual LIs for each of the text
that the people put in. But as you notice, this is actually bolds and breaks, and so
on and so forth. This is actually HTML, so we're going to change it a little bit. I mean,
let's say, actually, the data is HTML, so this is called a filter, so we can massage
the data before we show it. So now we do the same exact thing and voila! We have individual
Google Buzz chats from them. So now, I'm going to do next is--I already prepared a nice CSS
for us, so I'm going to cut and paste this CSS here. If I do that, then I should get
already a prettier view.
So, just a little CSS magic to make it nicely formatted. Okay, so what's the next thing
we would like to do? The next thing we'd like to do is we'll probably like to put a who
is buzzing this particular thing on the top? But by the way, let me stop for a second and
ask, are there any questions? Yes? >> What was the NG tag you used?
>> HEVERY: What was the NG tag? You mean, "ngrepeat"? Okay, so this is a good point.
Let's stop for a second. What am I doing here? What I said earlier is that Angular teaches
the browser new tricks, right? It is what HTML would have been like if it was designed
for building web applications. So, one of the common things, for basically, we need
to do in web applications is templating, right? And HTML is almost there, but lacks certain
things. And so, what if we could basically create what I call mark-up and directives,
which is basically brand new attributes that the browser doesn't understand. What if we
could just add it to the browser's vocabulary, so that when the browser sees this, it will
run this? So let me point out something interesting. I'm just going to disable this script doc
for a second by putting an X over here and I'm going to refresh this. Notice that it's
just HTML, nothing special. It's served at a "file://." There is no server processing
anything. All the magic is happening on the client. This really is a smarter browser.
Just by re-enabling that script tag, all of a sudden, we're back in business. Does that
make sense? Okay, any other questions? Yes? >> Can you create a more than one iFrame and
[INDISTINCT]? >> HEVERY: Yes. So the question is, can you
create more than one iFrame and things, right? >> More controllers to be exact.
>> HEVERY: More controllers, exactly, yes. The answer is--I'm just giving you an introduction
to what this thing can do--yes, we understand the concept of routes, controllers, partials;
we can include other HTML dynamic, load them in. There is no limit to what you can do.
And also, what Angular actually is, if you step back further, is actually HTML compiler
on the client. Now, if you think about it for a second, it sounds like an oxymoron.
Like, "What do you mean HTML compiler on a client?" It actually allows you to give meaning.
What does it mean meaning? It allows you to attach JavaScript behavior to any HTML primitive,
either an element, an attribute, a tag or a piece of text, and that's what we're doing.
There is a function somewhere that says, "If you come across an NG controller in your HTML,
then execute this piece of JavaScript which makes it look like there is a controller.
If you come across a double curly, which is over here, then do some other work. If you
come across an input type text, well then, register a listener on that input so that
as the user type, I can update the model, right? And so, what we'd really have is just
an HTML compiler that executes in the client. And I believe somebody else had a question
or was that already answered? It was answered. All right. Okay, so let' see if we can go
a little further. So, I'm going to cut and paste a little bit of stuff from my existing
thing and that is to make it a little prettier.
Now, notice this is very little, you know, really trivial amounts of code that I'm pasting
here. All I'm doing here is I'm adding--oh, yes, you're required. And I messed something up. You are--oh, yes,
I copied this in the wrong location. And fetch doesn't do the work because I have--all right.
Okay, I did some other magic here. So, let me show you what we're trying to get to. What
we're trying to get to is if I hit refresh, I actually continue having the user I.D. in
here, right? And the nice thing about that is, you know, it's bookmarkable. So I can
take the bookmark and email it to somebody. Not only that, my back-button now works and
if I go to previous, you know, it's at Google Buzz. This is the old already working client,
right? And so, I would like to get Deep Linking working in my application. So, obviously,
we--when I type in something here and I hit fetch, notice that the URL actually changed
up here. So, how did that work? That worked because the new code I pasted in, it says
"button on click, take the user I.D. and copy it into the location hash path," that's basically
the URL that you have. So we're going to do a little bit of changes on our Buzz client.
Oops. So, let's see. What we're going to say is in order to enable this, we're going to
say, watch the URL. And--all right, and if the URL changes call "this.user change" and
we're going to have a user change method that says if the URL changed it, then copy "this.userid,"
copy the location. All right, that's the URL of the person we want to get a Buzz information;
copy it to user I.D. The reason we're copying it to user I.D. is because we're trying to
get it into our input field over here, that's the user I.D. field. And then once we have
it, I want to go and simply go fetch all of the activities for that user I.D. So now,
we have an exception, line 12. >> [INDISTINCT].
>> HEVERY: Oh, yes, thank you very much. Here we go. So, what does this do? What it does
is that we are watching the URL, which means if I go and change this to Google Buzz, hit
enter, notice it automatically copied it into the input field and also, it fetched the data
for our application. What that does is that the back button now works. If I hit back button,
I go to miskohevery. If I go forward button, I go to Google Buzz. Now, for those of you
guys who have done GWT or AJAX roll, getting Deep Linking to work is a nightmare, right?
Okay, nobody has done it apparently because nobody is shaking their heads, but yes, it's
a nightmare. And this actually is pretty trivial if you think abut it, right? You're just watching
the URL. If it changes, you call in some method and things get updated. Now, I want to show
you one more thing and that is if I click on "replies," currently, it doesn't do anything,
but if I click on "replies," I would like to go and show all the replies in line. So,
I'm going to, again, just copy this piece of code. So, I copied an "expand replies" method and
all it basically does is it says if I don't already have a replies, then go and fetch
them over here, otherwise, flip a flag called show, and we'll deal with the flag in a second.
So, that makes it--but if I click on it, it will go and fetch additional data. But the
problem is our template doesn't show any additional data. So, let's go back to our template and
[PAUSE] I'm trying to remember where to paste this. Oh, I think it's right here. Here we
go. Yup, so here comes our replies. So what did I paste over here? I simply said, "Give
me another URL," the LI inside of it repeats for every reply in 'itemreplies.dataitems,'"
and the reason why it's "dataitems" is because we wrote into the activity replies, right?
The "itemreplies" now contains the new data and we showed the image in the URL and, of
course, the content HTML. And so the end result is that we can see the replies being in-lined
in our application. So I can go to any--let's--oh, of course, it's not a--there's no way to hide
it now, so what we need to do is we need to say, " if," that's
the bullion flag that I had a second ago. Expand, collapse, right? So we can expand
and collapse this. Oh yeah, and it will be nice if I could search up here, right? So,
the searching is actually very trivial because all one has to do is when you go--when we
iterate over the items, we simply say, "dot filter" on this input field over here. And
now, we can see if anybody is buzzing about me, and the answer is no. Node? No. Google,
well, that's probably everywhere. I see, okay, New York, here we go. New York, here we go.
So, searching--continuous searching is really, really trivial because, you know, Angular
kind of behaves like a spreadsheet; you change a variable and all the other pieces automatically
recompute and all this magic is happening through data binding. So, I want to show you
one more thing and then I'm going to kind of talk about more of the structure of it.
If we go look at the final product over here, if I click, "replies," notice that it kind
of scrolls. This might be too many replies in here. Here, notice it kind of scrolls up
and then scrolls back down when it closes. And let's say we want to add this effect to
our application. So, what really we want to do is say something like this, "My expand
showů" or, "Expandů" when, basically, this thing is there, right? So, I just made that
up basically a term called "expand." HTML browser doesn't know what it is and neither
does Angular. And so, actually, nothing is going to happen if I--I'll show that to you.
If I expand, the items will come, but they no longer collapse because I took the show
part out and of course, none of the magical scrolling is happening. So how can we add
the behavior? Well, this is where you can take away from existing libraries, like jQuery
or Closure or Dojo or any other JavaScript libraries that are already out there and you
can integrate them in. So what I'm going to do here is I'm going to basically copy a little
bit of code that teaches Angular new tricks or rather, teaches the browser new tricks.
What I'm saying here is this, if you come across my expand tag, then I want you to execute
this function. And this function basically says that the element should have a CSS property
display block. And the reason why it has to have display block is because browsers has
never seen it and so, it doesn't know whether it's an inline or a block property. This is
a compiler directive that says keep on compiling; the stuff that is underneath me should be
compiled as well. And because it's a compiler, it has two phases; there's a linking phase
and a compile phase. So the first function we return is a compile phase, which gets to
massage the HTML. But because you're inside of a repeater, you might have to re-link once
for every instance of that repeater, right, because repeaters can expand and collapse.
So this basically says--okay, here is a compile function which basically says, "For each item
inside of a repeater," if you happen to be in one, "Hide the element by defold, watch
the expression expand," that's because we created an expand attribute over here. So
whatever is in there, grab that element and then watch it. If the variable changes, then
if the value is true, then create--this is jQuery, by the way, so create the slide down
behavior, and if it becomes false, then do the slide up behavior as well. So, we have
to include jQuery in our application, but it doesn't have to be jQuery; it could any
other existing library that you already know and love. And now, if I refresh this and if
I grab something that doesn't have too many replies, you see we have the scrolling up
and down. So we are teaching the browser new tricks. So the way to think about this thing
is that your HTML is your view and HTML basically is kind of a DSL, right? It's a Domain Specific
Language for laying out your document; that's what the HTML is. But what we're trying to
do is we're trying to expand that DSL into realm of what is useful of building web applications?
Well, what's useful for building web applications is stuff like repeaters conditionally showing
and hiding things, creating listeners, firing off things, copying data back and forth, and
so on. So we added all of this out of the box, but really, we give you the freedom to
add anything else that you want into HTML and basically, you have to build out your
own language to it. And now, somebody asked me if you--if we can do something more complicated
with this thing, and the answer is yes. We have something called services. One of the
services, for example, URL routing service, where you can say, "If the URL looks like
this, then load this controller and this partial. But if the URL changes, then load some other
controller and some other partial," and then, you can nest these partials into each other
and you really assemble the application on the fly in a browser. Does that kind of make
sense? All right. Questions? Okay. So, let's see. Let's go back. So we kind of did a demo.
Now, I mentioned earlier that it's a compiler and so, I kind of highlighted a couple of
things in here for you. The area in yellow, that's this thing over here, we call this
a widget. So if you come across any--either something the browser knows how to render
like an input tag or something the browser does not know how to render, something you
create your own, you can cause the compiler to trigger some compile function. So in our
case, what we trigger over there is a listener that says, "Okay, register a listener on the
input field. If the input field changes, then copy the value of the input field from the
email into the controller," right? And oh, by the way, this better be an email; something
that I haven't shown over here, but I should. For example, if I delete the text over here,
it becomes red, and if I hover over it, it says, "Well, it's required." And how did it
know that? It knew that because our user I.D. has an attribute called ngrequired. And so,
I added the meaning to an input field. I said, "Well, if you see ngrequired, then complain
if you don't have a particular attribute." So this is what we call widgets, right? And
you can write your own. We also have a concept of directives, which is additional attributes
that are added to existing elements, which basically change behavior. So, one that I
showed you is the repeat element that basically says, "Oh, take this as a template and repeat
it for once in each of the following expression." And the expression can return either an array
or a object, but more importantly, the expression gets reevaluated whenever anything changes.
So this filter function gets reevaluated whenever email changes up here. So this email over
here causes this expression to reevaluate and then the repeater either adds or removes
the LI elements into your DOM tree to produce the rendering. This is a markup that you see
over here. This basically--we can intercept any text and give it meaning. So, I chose
the double curlies as a way of dealing with this thing, but you could create your own
expressions inside of HTML or own text that means something special to you, and you can
attach behavior to it as well. And then we have a concept of a filter, which is that
it takes the value of this and runs it through another function to make it uppercase. This
is very common when you need to format your data into a locale or internationalize it
or something like that; maybe, INTNN, et cetera. And then, here is an example of a brand new
widget, like a switch statement that you're all familiar with from programming. It really
doesn't exist in HTML, but we can create one by simply saying "Switch on" some particular
expression, and if the expression has the word "home" then show, this div. But if the
expression has, let's say, account, oops, then go and include another HTML file called
"account HTML" from a different location and then inline it into this particular thing.
This goes back to somebody's questions over here whether we could have partials. So I'm
just kind of showing how you can turn HTML into a DSL so that you can build up anything
that's meaningful for yourself. One of the things we, for example, we do on our project
is that we have a--we say "button" all over our HTML, but we really want to have a nice,
pretty closure button. So we have a director that basically says, "Oh, if you come across
a button, replace it with this really fancy closure button." And so, our HTML is nice
and clean without having to go into details of adding CSS and et cetera to make it style
properly. Okay, I want to talk about data binding for a second, which might not have
been obvious. So data binding is kind of one of those overloaded terms that is used all
over the place. And so, in most templating systems that I have worked with, they have
this property that you have a template and you have a model, and you merge the two and
you produce a view. And this is a one-way street. That is, if the model changes, you
have to remerge with the template and you have to change the view. And the problem is
that what if the user has modified the view in the meantime? You're basically clobbering,
him right? And next, working with these kinds of templating system, kind of great for initial
rendering of the page, but then you have this whole second problem is how do I get the data
back out of the page and into a model? So, what angular does is it does something I call
two-way data binding. And the idea is that you take a template and you compile it into
a view and then the view and the model become tightly interlinked. That is, whether the
user goes and changes the view by interacting with the HTML, for example, an input field
and changes a field inside of it, or the JavaScript changes a property on some model; it doesn't
matter. The data is immediately reflected on the other side. So if the JavaScript changes
the model, they view updates. And if they view--if the user changes the view, then the
model updates, and this happens continuously. So what ends up happening is that your model
is the single source of truth of application. You never have to parse data out of HTML.
You never have to worry about like, "Well, did the user type something somewhere and
so maybe my model is stale or something like that." The model is always the truth. And
so, here's a couple of more places where we can read up on this. So there's, of course,
the, which is where we have most of our documentation and the things related
to Angular. The current demo you can see over here and also the demo that I've kind of done
over here and the idea of resources is kind of placed up there as well. So I'm going to
open up to questions. Yes? >> So I've heard that filters are more for
[INDISTINCT] by a limited number of [INDISTINCT]. Can you create your own filters?
>> HEVERY: Yes, the question is can you create your own filters. Everything that you see--so
let's go back to this page--everything that you see, everything that Angular does is completely
pluggable. So what Angular is in its rawest form is just HTML compiler and it has no preconceived
notions about anything. So everything that you see on this page can be overridden, changed,
extended, added or everything else that you desire. So if I wanted to add a new filter,
all I have to do is say "angular.filter" and then specify the name of the filter equals
function and off I go and write my own functions. Filters can be chained. Filters can have properties
added to them and so on. So, the other thing--right, yes. Other questions? Yes.
>> So you mentioned there's a--sorry if I messed this up that if the browser is [INDISTINCT].
>> HEVERY: This is--so the question is what is the compatibility really with the browsers
on this thing? I think the currently--in theory, this runs on IE6, but there are some issues
with certain things like hovering, et cetera, which would require a little more love, which
we could get. But as far as I know, IE6 is basically unsupported. So IE7 and higher,
this thing works. It also works on mobile browsers which are WebKit-based, we have it
tested on. So all your grade-A browsers, this thing works just fine. Yes.
>> I can see that as far as the demo goes, how well does it work in terms of it's like,
you know, integrating with the database and then updating in that database and immediately
showing it on the browser in terms of like speed compared to like for Angular.
>> HEVERY: Right. So you are asking about speed in terms of updating a database. So,
Angular really doesn't say anything about that. What angular is is a way of rendering
your content on a page, right? Now, typically, the way it works is that you have a--what
we call, a resource. So, this particular resource has some URL and you can do get, you can do
post, you can do save on this particular URL, and write JSON to it. How you handle it on
a server side is obviously your problem and that's up to you, although, we have a second
project called Arestia, and one day, we'll give a talk on that as well. But really, the
only thing we provide is a way of calling a dataset or calling a URL on a server. The
other thing we provide is--I'm not sure if you guys noticed, is this statement over here
is really--looks synchronous, right? I mean, for those of you guys who have been here for
Ryan's talk just before mine, you know, everything in JavaScript is really asynchronous. So how
is it even possible that this thing executes? It turns out what the activity that get does
is indeed asynchronous, which means it makes a call and at some point later, the data comes
back to me. But because of magic of data binding, what the activity that get does is it returns
an empty shell object and it saves it into activities and then the data binding simply
renders nothingness. Then at some point later, the resource comes back with the data and
pre-populates that already empty shell and the data binding takes over and renders everything.
And so, what's missing out of this code, for those of you who have been building AJAX applications,
is all of the code backs. All the code backs that are usually just littered throughout
your code base, whether it's for listening on buttons, events, or talking to the server,
are notably absent if you look through this piece of code. It's not that they're not there,
it's that just we're using clever techniques of returning shell objects and relying on
the fact that the data binding immediately takes effect that we simply don't have to
deal with them. You say, "Go do this." You kind of cue it off and say, "Go fetch the
data. And once the data comes back," you know, "Shove it in here. And you know how to render
it. You don't need to involve me in the rendering process because I already told you everything
about rendering inside of the view." Yes. >> So with all this public computation, how
much [INDISTINCT] usage [INDISTINCT] how much does the memory browser actually increase
[INDISTINCT]? >> HEVERY: I'm sorry. I'm having a hard time
hearing you. >> I'm sorry. How much does the memory and
stuff the browser actually increase with all the information that is [INDISTINCT]?
>> HEVERY: Okay, good question. So, the question is how expensive is this on a browser? We
have done some measurements, not a lot. We're working on improving the speeds. I think we
have an internal application that we are building using Angular--and I should point out that
the application was built using GWT before that and when we rewrote it in Angular, we
went from something like 17,000 line of code to about 1,000 lines of Angular code and now
the application does a lot, lot more and it's actually 2,000 lines of JavaScript code. So,
you get tremendous amount of savings. In terms of speed, the load time is very fast. I think
it's something on the order of 300 milliseconds to load, render, compile, and do everything.
And I haven't really done much in terms of optimization yet. And as far as a live typical
page that contains a reasonable amount of data, you're looking about something about
two to five megabytes of JavaScript code--data code that's kind of running in the browser.
This is for Chrome, so IE might be different, a little higher, a little larger, et cetera.
>> How much is the entire library worth? >> HEVERY: How much is the library? Yes.
>> [INDISTINCT]. >> HEVERY: The library itself is under 50
kilobytes compressed on obfuscated. I have some ideas on how to make it even smaller,
so in the future, it might even get smaller. One thing that I like about this set up is
because so much of it is declarative inside of the HTML, as the library gets--as the Angular
library gets smarter, better and more efficient, right, everybody benefits because you described
how the application behaves rather than programmed every little nuance in every single callback.
And so as, over time, Angular gets better, faster, supports more browsers, new application
kind of gets it for free. Yes. >> Question through VC.
>> HEVERY: Okay. Go ahead, VC. I got you. >> Our apologies for just barging in. So I'm
wondering about the DOM stability. So when Angular goes and recomputes the result of
the constraint system's output and then generates new HTML, does it make any attempt to keep
all DOM notes that didn't change around once we place them or does it just wipe them all
out with an HTML? >> HEVERY: Good question. So the question
is how do we do the updates whether we do inner HTML or whether we modify the DOM. Currently,
we are modifying DOM in place and we're trying to be really smart about only talking to the
DOM when we know something has changed because it turns out that although WebKit is pretty
good about talking to DOM and manipulating it, in IE, it's an absolute nightmare. You
know, every single call to a DOM manipulation, you should be really careful about that you
absolutely have to do it. And so we're really smart about manipulating the DOM as it is
right now. However, there seems to be some evidence that, you know, using just a brute
force inner HTML might actually work better. And so, in the future, it's possible that
we're going to rewrite this particular process to just purely dump inner HTML into the whole
page and just refresh it that way. It depends. You know, we'll see how their performance
is going to end up, which one's going to be faster, but as of right now, we modify only
the stuff that has changed. And keep in mind that because of bidirectional data binding,
anything that the user interacts with the DOM is really inside of the model and so as
long as the model gets preserved, we can redraw the DOM in exactly the same state. So, that
really isn't a problem of do we accidentally clobber something when we are redrawing, like,
it's not an issue. And I think you had a question, right?
>> Yes, so now that there's a lot of declaratives that is sent out that you put into HTML. How
hard do you find to test it? >> HEVERY: I'm sorry, I missed the second
part. >> Do you find if hard to test now that there's
[INDISTINCT]. >> HEVERY: Oh, testing. Yes, thank you very
much. Is it hard to test this thing? Oh, I'm sorry, how can I forget? Mr. Testability,
myself, right? Thank you. It's almost like you cued this up. No. Thank you for asking.
I love testability. So for those of you who know me, I test drive all my code and testability
is something I take very, very seriously. And so, let's talk about this for a second.
Imagine that you wanted to test the Buzz controller that I have just created. Look at this piece
of code. Is there anything in there that makes it hard to test? And the answer should be,
"No, there's nothing in there that's inherently difficult." And the reason for that is one,
we're not manipulating any sort of DOM inside of the controller, which means I can just
instantiate the controller and off I go, call methods on it and do any behavior I want.
But there is one thing that kind of is a problem and that is this whole activity object, right?
Well, it turns out resources are so important and so common that we took all the stuff that
the browser has and that we call--I affectionately call "the global state of the browser," all
the nastiness that's inside of the window, and we hid it behind this service called "the
browser." And for testability, we actually give you a mock browser. So, in production,
you get a real browser. Because we have dependency injection, we inject a real browser into your
application and that, you know, has the global state that comes with the browser and it's
all in there, but in your test world, we give you an additional JavaScript file which hooks
it up so that you get a mock browser and then what you can do is you can train, for example,
exit char request. So you can say something like browser exit char expect get on this
URL respond with this. And then you can write your controller and you can write a test that
basically says instantiate the controller and the controller, let's say, in some method,
goes and tries to talk to a resource. The browser says, "Oh, yeah, I already was trained
that I was expecting this particular get," and so it responds with the appropriate data
and you can control at what points the data comes back through flushing et cetera. So
testability story is really, really nice, both because we provide these higher level
objects that hide all the nastiness of the browser and also because at no point in your
code do you have to touch the DOM, right, because the DOM is a separate piece of--the
DOM is really a view and it's a projection of your model. So you don't modify the DOM,
you really just modify the model and model is just a plain old JavaScript object. So
that's one thing that you can do in terms of unit testability, you know, great story,
awesome stuff. For intuent test, we are working on a an intuent framework. In a way, you can
think of it as a Selenium, but the problem is the Selenium--is that Selenium doesn't
know how Angular works. And so, if Selenium clicks on a button, it doesn't know when Angular
says, "I'm done redrawing. You can go and look at stuff." So our framework actually
closely works with the Angular engine and so you can say stuff like, "Navigate to a
particular URL and then," you know, "Verify that this button is present." But the framework
is smart enough to say, "All right, navigate to particular URL," really means that Angular
has to run all the stuff and all these things are changing and so I have to wait until Angular
says, "I'm done," so you can go on to the next step. And so, it takes away all of the
pulling and all of the nastiness that you really are faced with in typical trying to
do an intuent testing in your system. And so, you have nice, simple, declarative way
of saying, "I expect these things to be true." And the intuent framework works closely with
the Angular engine to make sure that it executes nicely and you don't have any weights and
it runs pretty quickly through the system. So, thank you for the question. That was awesome.
Yes, five minutes. Yes. >> I have four questions.
>> HEVERY: Four questions. All right, let's do it one at a time.
>> How many people are working on this? >> HEVERY: How many people are working on
it? Mainly, myself, there's another guy Adam Abrons, who works on it external to Google.
Also, there's the team in Google who is using it to build an internal application and those
folks, from time to time, there's about six of them, go and add stuff into it, but I'm
usually the guy who does most of the heavy lifting over here.
>> How is it licensed? >> HEVERY: How is it licensed? MIT.
>> How long is the adoption? >> HEVERY: How is the adoption? So far, we
have a couple of people outside of Google and two people inside of the Google. The people
who are doing inside of the Google are actually some of them are sitting in the audience.
They absolutely love it. I mean, how could you complain when you delete 17,000 lines
of GWT code and replace it with 1,000 and you have a beautiful testability story and
so on? So they love it. >> Are there any live examples [INDISTINCT]?
>> HEVERY: Yes, so you can go to documentation, It's still work in progress.
I'm working on this daily. This is, for example, a Media Wiki for those of you who are familiar
with it. Media Wiki is just what Wikipedia uses. The cool thing is you can go and edit
the pages, so as long as you register yourself. The code is directly embedded in--the code
examples are directly embedded inside of the Wiki. They automatically render into this
kind of a view that basically shows you what the HTML looks like, plain and source, and
you can actually play with the examples directly inside of the Wiki. If I go to source and
I copy this code, I can paste it into a file on your--my desktop and I can go off and play
with this particular snippet as well. If you click on the documentation, you know, a lot
of these things are explained over here, all the attributes, all the magic that we currently
support. The cookbook contains typical things, you know, how do you do Hello World, how Basic
Forms are usually done, how do you model the controllers; deep linking with pages, somebody
was asking me over here; external resources, which is basically the Buzz demo client which
I have done over here is done here again in the 50 lines of code. As you can see, I can
fetch the Google Buzz directly in here. You can look at the source code directly in line.
So those are good resources to go and look at. Other questions? Yes.
>> So what are the open issues and biggest problems for...?
>> HEVERY: What are the open issues and biggest problems? My biggest problem is explaining
to people what it is. It is--you know, people have these buckets in their head like, "Oh,
it's a library. Oh, so it's just like Closure." Well, no, actually. Angular can actually benefit
from Closure because Closure has lots and lots of widgets that you can actually use
with Closure. "Oh, Angular is like jQuery because it manipulates the DOM." Well, actually,
Angular uses jQuery to manipulate DOM, but it's not the same thing as DOM manipulates
your framework because I only give you an API to manipulate the DOM, right? There's
all this data binding that happens for you. People say, "Well, it's a framework for building
web apps." Well, it's not really because really, it's all about the HTML and teaching the browser
new tricks. So, explaining to people exactly what this thing this is--is I'm having a heart
trouble. So if any of you are good at marketing, talk to me and help me out here. What's the
second question? >> What are the problems?
>> HEVERY: What are the problems? Open issues, let's see. What are the open issues? We have
some issues with--when the data sets get really large, Chrome just chunks through them, no
problem. Like, I may have to build some app that would not run fast in Chrome. Same thing
for Safari; Firefox is reasonable; IE sometimes has troubles and so one of the things we want
to really focus now on next is making sure that this thing performs on IE just as well
as in all the other browsers. Now, when I say "make the performance better," I don't
mean that it's currently slow. What I mean by that is if you have a large dataset, like,
let's say you want to have a table with a thousand rows and each row contains 50 different
bindings in it, right, and then you do something, it might take, you know, a little bit of like--just
enough lag to know that it's not instantaneous, right? And I want to get rid of that. I want
to make sure that on all browsers, it's essentially instantaneous. And so I have some ideas on
how to make this thing better and so it should probably get better with time. The other thing
I would like to do--and I'm hoping that some of the open source community could take on
to it--is, let's say I wanted to have charts inside of Angular, right? It would be awesome
if I could simply, in my HTML, say, "bracket pie-chart," and point it to a data source,
right? And so if the open source community will come up and say, "Oh, I'm going to write
maybe a--the glue between Angular and Raphael," which is an open source library or maybe Google
Charters or something like that, to make it so, you know. All of a sudden, if the new
person comes and says, "I want to have charts in my application," all they have to do is
drop a little bit of tag inside of it. No code necessary, right, maybe animation to
be included in there as well, and so on and so forth. So what Angular is today is a raw
set of primitives. It's not really a ridge--widget library or anything like that, which I'm kind
of hoping that people can pick up on. And I think we're out of time. So I hope you enjoyed
it and see you guys later.