We're sorry but this page doesn't work properly without JavaScript enabled. Please enable it to continue.
Feedback

From Knockout to AngularJS

00:00

Formal Metadata

Title
From Knockout to AngularJS
Title of Series
Number of Parts
170
Author
License
CC Attribution - NonCommercial - ShareAlike 3.0 Unported:
You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal and non-commercial purpose as long as the work is attributed to the author in the manner specified by the author or licensor and the work or content is shared also in adapted form only under the conditions of this
Identifiers
Publisher
Release Date
Language

Content Metadata

Subject Area
Genre
Abstract
So you've spent the last couple of years putting KnockoutJS code into production. Now that AngularJS is the new kid on the block, you can't wait to throw all those observables out, but where do you start? In this talk, Yngve takes a look at a Knockout application, finding ways to port it to AngularJS piece by piece, without having to start from scratch. We'll be looking at pros and cons of both frameworks, and making sure the effort is worthwhile.
Level (video gaming)SequelWeb 2.0Software frameworkInformation technology consultingService (economics)Server (computing)Source code
Software frameworkKeyboard shortcutLibrary (computing)World Wide Web ConsortiumStress (mechanics)Right angleWeb-DesignerKeyboard shortcutRevision controlSoftware frameworkFront and back endsCodeProjective planeEquals signModule (mathematics)1 (number)Web 2.0Core dumpRoutingBuffer overflowSinc functionMultiplication signView (database)Product (business)TwitterDifferent (Kate Ryan album)Order (biology)Functional (mathematics)Library (computing)SynchronizationEndliche ModelltheorieSign (mathematics)NeuroinformatikArray data structureGoodness of fitWeightStack (abstract data type)Cartesian coordinate systemBuildingGame controllerLie groupIntegrated development environmentMathematicsWeb applicationLabour Party (Malta)CodeDirected graphProcess (computing)Frame problemSolid geometrySingle-precision floating-point formatScripting languageWeb pagePoint (geometry)Metropolitan area networkCuboidMultiplicationInjektivitätJava appletHeegaard splittingSet (mathematics)Software developerLine (geometry)Algebraic closureComputer animation
World Wide Web ConsortiumSoftware frameworkModul <Datentyp>Java appletScripting languageKeyboard shortcutModule (mathematics)Boss CorporationData structureCartesian coordinate systemMultiplication signMUDPoint (geometry)CodeScripting languageWeb 2.0Process (computing)Web applicationArchitectureDifferent (Kate Ryan album)Goodness of fitCore dumpInformation technology consultingNumberDecision theoryInjektivitätRule of inferenceConnectivity (graph theory)Computer architectureService (economics)Mobile appParallel portMathematicsProjective planePlanningSubsetTask (computing)Group actionPairwise comparisonLevel (video gaming)NeuroinformatikWritingWebsiteState observerWordSoftware frameworkForcing (mathematics)Game controllerRevision controlDampingInstance (computer science)RoutingComputer fileWeb pageSingle-precision floating-point formatReal numberUniform resource locatorCASE <Informatik>Computer animation
Menu (computing)Sheaf (mathematics)Scripting languageHyperlinkWindowInfinityDemo (music)Matrix (mathematics)Hydraulic jumpLibrary catalogGroup actionMoment of inertiaDigital object identifierGamma functionFunction (mathematics)Fiber bundleContent (media)Data managementInternet forumLocal GroupoutputInverse elementData typePrice indexAreaMeta elementAnnulus (mathematics)Convex hullControl flowFree variables and bound variablesComputer iconMaxima and minimaQuicksortOpen sourceCartesian coordinate systemUniform resource locatorWebsiteChainLink (knot theory)Enterprise architectureCodeModule (mathematics)Keyboard shortcutFunctional (mathematics)Projective planeDemo (music)View (database)Different (Kate Ryan album)Message passingEndliche ModelltheorieElement (mathematics)MereologyDirection (geometry)Attribute grammarWeb pageMobile appPoisson-KlammerMagic squareGame controllerDivision (mathematics)Right angleMultilaterationVideoconferencingGoodness of fitComputer fileRoutingSource codeService (economics)Coefficient of determinationAreaProcess (computing)Greatest elementJava appletScripting languageSystem callCASE <Informatik>Food energyAnnulus (mathematics)Data structureWordBitObject (grammar)Software developerInstance (computer science)CodecResultantMatrix (mathematics)Key (cryptography)Electronic mailing listOrder (biology)Computer animation
Function (mathematics)Demo (music)WindowElectronic mailing listGame controllerDrum memoryHost Identity ProtocolService (economics)InjektivitätSubject indexingCodeMathematicsGame controllerCartesian coordinate systemGoodness of fitFunctional (mathematics)Regulärer Ausdruck <Textverarbeitung>Electronic mailing listParameter (computer programming)Data managementView (database)Template (C++)Core dumpContext awarenessRight angleOrder (biology)Module (mathematics)Revision controlPoisson-KlammerComputer fileDefault (computer science)Software developerSign (mathematics)Home pageElement (mathematics)Endliche ModelltheorieString (computer science)WebsiteMereologyScripting languageObject (grammar)Java appletComputer clusterVideo gameProjective planeLattice (order)CASE <Informatik>Multiplication signAngleSquare numberDifferent (Kate Ryan album)Total S.A.Computer animation
Electronic mailing listGame controllerFunction (mathematics)WindowHyperlinkSocial classCurve fittingDrum memoryComputer iconFinite element methodMaxima and minimaExecution unitMoment of inertiaScripting languageFood energyFunctional (mathematics)Service (economics)BlogSource codeElement (mathematics)Game controllerDirection (geometry)Basis <Mathematik>ResultantContent (media)Link (knot theory)Electronic mailing listSign (mathematics)PressureCantor setCASE <Informatik>Bit rateLoop (music)Keyboard shortcutCodeRaw image formatText miningView (database)Line (geometry)Software testingMultiplication signDot productEndliche ModelltheorieRoundness (object)Set (mathematics)Process (computing)Different (Kate Ryan album)Attribute grammarHash functionHyperlinkRight angleEqualiser (mathematics)Hand fanOrder (biology)2 (number)Goodness of fitWritingTerm (mathematics)Regular graphUniform resource locatorMobile appDatabase normalizationComputer animation
Matrix (mathematics)Surface of revolutionDemo (music)WindowHyperlinkSocial classHost Identity Protocol2 (number)AreaKeyboard shortcutService (economics)Category of beingObject (grammar)Computer animation
Function (mathematics)WindowMenu (computing)ChainUniqueness quantificationSocial classHyperlinkGame controllerInterior (topology)Coma BerenicesExecution unitDrum memoryEmailMoment of inertiaElectronic mailing listSocial classGroup actionView (database)Multiplication signFunctional (mathematics)Category of beingChainUtility softwareFree variables and bound variablesResultantOrder (biology)Finite differenceLibrary (computing)Keyboard shortcutWordComputer clusterQuicksortFlow separationWebsiteCurvatureHookingFood energyNeuroinformatikObject (grammar)AreaEqualiser (mathematics)NP-hardKnotSet (mathematics)Entire functionString (computer science)MathematicsComputer animation
WindowDemo (music)Lemma (mathematics)Chi-squared distributionLattice (order)HyperlinkDiscrete element methodMenu (computing)Inheritance (object-oriented programming)Computer animation
Coma BerenicesWindowSocial classCategory of beingElement (mathematics)WebsiteElectronic mailing listDirection (geometry)MereologyFood energyComputer animation
Adventure gameQuantumWindowMenu (computing)System callMatrix (mathematics)Coma BerenicesDemo (music)MereologyInsertion lossElectronic mailing listAreaCodeComputer animation
Demo (music)Object (grammar)Sinc functionElectronic mailing listGroup actionCuboidProcess (computing)CASE <Informatik>Computer animation
Matrix (mathematics)Adventure gameDemo (music)HyperlinkMoment of inertiaMenu (computing)Electronic mailing listCuboidFilter <Stochastik>CountingResultantMultiplication signDisk read-and-write headMusical ensembleRight angleComputer animation
Adventure gameInfinityFree variables and bound variablesAttribute grammarDirection (geometry)Object (grammar)NumberResultantCountingHookingCASE <Informatik>Element (mathematics)Right angleWordEndliche ModelltheorieSineComputer animation
Demo (music)Host Identity ProtocolInfinityAdventure gameScalable Coherent InterfaceLocal GroupView (database)WindowoutputTexture mappingForm (programming)Function (mathematics)ResultantData miningSystem callEmailView (database)Electronic mailing listEndliche ModelltheorieDirection (geometry)Form (programming)NeuroinformatikCategory of beingHeegaard splittingCuboidFlow separationAddress spaceSimilarity (geometry)Instance (computer science)String (computer science)Link (knot theory)outputWebsiteMultiplication signRegular graphComputer animation
Scalable Coherent InterfaceFunction (mathematics)Game controllerElectronic mailing listWindowMathematicsModule (mathematics)CodeSoftware frameworkTrailService (economics)Key (cryptography)Green's functionLie groupAxiom of choiceProjective planeMultiplication signCategory of beingEqualiser (mathematics)Functional (mathematics)Computer animation
Computer animation
Transcript: English(auto-generated)
All right. It's great to see so many excited people in the audience. This is quite the intimate stage, isn't it? I guess some people are still coming in. That's fine. We'll just get started. My name is Ingwe Baknilsen.
I work as a senior consultant for Novana. It's an Oslo-based consultancy company. I do all kinds of stuff, all from web to down in the nitty-gritty SQL server services stuff, but I really like... I have a passion for the front.
I like all the frameworks, all the jQuery stuff and the Knockout stuff and Angular stuff. Let's see if I can get this to work. There we go. What's this about? I'm here to talk to you about from Knockout to Angular. That's the name of the talk and the name doesn't lie.
It's simply... If you find yourself in a situation where you have a lot of Knockout code and you decide for some reason that you want to go for Angular instead, if this is your personal project, that's fine. I mean, just do it. It tends to be a little more complicated if it's in a production environment.
If you have a lot of code and things are already live, you have customers dependent on your web application, you can't just rip the whole thing apart. I am going to talk to you about how we can do this in a step-by-step manner and how we can do it successfully
and what you have to think about. Why did I choose Knockout and Angular? Well, first of all, I've been in a project for a couple of years now where we chose Knockout as our front-end data binding layer. It ends up being used to do a lot more than just data binding.
But still, we have a lot of Knockout code in production in a couple of web applications for my customer right now. I really like Angular. I think Angular is cool. Like all developers, if something is cool, we want to try it, we want to use it, we want to adopt it. It happened with jQuery, it happened with Knockout, Backbone, Ember, Angular.
Angular has quite the traction. This is from Trends. The poor little blue guy down here, that's Knockout, hasn't really been that trending. Angular, on the other hand, since July 2012,
it's kind of skyrocketing. This is not just because I think it's cool. I think this is a good sign that Angular is a solid framework. It's probably here to stay. And with the recent news of Durandal converging into Angular as well, that just kind of builds up under that assumption
that Angular will be around for a while, it will be supported for a while, and it will probably be improved a lot. We're currently in 1.3. I don't remember the exact version we're on now, but Angular version 2 is coming out anytime soon, maybe in this year or maybe next year,
but at least something is happening. Now, there's a couple of other reasons. Knockout is advertised as kind of an MVVM framework, model-view-view-model framework. I don't agree. This is my humble opinion,
and I don't agree because I think Knockout lacks kind of the concepts that make up a framework. You don't have a concept of a view model in Knockout. You have kind of some, this is how you build a view model with JavaScript already.
So what Knockout really gives you is kind of the data binding stuff. It's a data binding library. I wouldn't call it a framework. It's a library. Don't go around telling everybody that Knockout is a library. This is my opinion. It does this really, really well.
It binds your JavaScript code to your DOM, and it does it quickly. It does it well, and I mean, you have pretty good control over the DOM. But the problem arises when you're building something more than just pushing data out to the view.
You probably need some data access. You probably need some, maybe you're building a single-page application or a multi-page with single-pages stuff in them, and all of a sudden, you need to pull in a bunch of third-party libraries or frameworks. So all of a sudden, you need some routing framework.
You need something to access your API. The most common way to do that is to use jQuery and just use GETs and posts and stuff like that. Still, you're dependent on the jQuery framework, which is a reasonably big chunk of code in itself.
Now, jQuery is fine because it's continuously developed and improved, but there are a lot of other frameworks that you get on the Stack Overflow article, and you get some suggestions. Use this. Use this for routing. Use this for data access and stuff like that. And you pull it in, and you deploy it to production,
and everything is fine. And after a while, the project that does your routing, all of a sudden, it's no longer supported. Maybe the guy just left for a desert island and didn't want to do JavaScript anymore. And now you're in trouble because if one of the other frameworks is dependent on that and so on and so on,
you have a lot of dependencies, and all of a sudden, one of the frameworks doesn't support a newer version of another framework. So now you have to switch out that framework and use something else. That could be a problem. I'm not saying it's always a problem, but it could be a problem. So Knockout, in order to build a full-fledged application,
you need a lot of different third-party frameworks. There's a couple of other things I don't like about Knockout. Now, this is not a round. I've been using Knockout for quite some time, and I do think it's a good framework, but there are still things I don't like. I just like Angular better. And one of the reasons is this.
Or should I say self? How many of you guys do Knockout? That's quite a lot. How many times did you write this? Yeah. You can count it on a... Yeah, I would need a lot of hands to show that, actually. I've probably written it thousands of times. And, of course, it kind of makes sense
because we're working in JavaScript, we have closures, and we have the this scope and everything. So it can get messy. So self this is kind of a safety net in order to do stuff correctly. And then it's this. This kind of thing here. The observable, the observable arrays. You need these.
You have computers as well and stuff like that. You need these because Knockout depends on them to keep the view updated. And the view model updated. So if it's two-way binding, it keeps everything in sync. So you need this in order to tell Knockout that this is something you have to watch. You have to subscribe to changes
and you have to push it out to the DOM and you have to do all this kind of stuff. So now something is a function and you can't just use the equal sign. How many of you have tried to say self that something equals some value after you made it observable? Yeah. A couple. I've done it a lot of times. And nothing works. And I'm thinking, ugh.
And I don't see the point, really. Because you can obviously do it without the observables, as we know from Angular and other frameworks. Now, Angular, on the other hand, is what I would classify as a web framework. It's a fully-fledged framework
for doing web development. By just downloading the core, you have dependency injection, which, if you use Knockout, you'd probably use require.js, something like that, for that. You have routing, not in the core, but you have a routing module. You have a REST API, the resource module,
that helps you do REST requests in a very, very fluent manner. Out of the box, you get the HTTP request that you can do just with the Angular core.js. You can do simple HTTP requests, gets, posts. We'll look at that after in some code.
So now we have one huge monolithic thing. So many think that is bad. But since I think it's version 1.1 or something, they split up a lot of these modules into smaller packets.
So you can just pick and choose the ones you need. You get a long way with Angular core. And then you can pull down the routes, and all of a sudden you have single-page application routing facilities. And, of course, dependency injection is already there with the core. So, in other words, it has a bunch of modules, which I think is very good.
And, of course, what's important about that point is that all these are modules developed by the same team. They're supported by the same team, and the versions increase parallel. So if they do an upgrade, they make sure all the components work together still.
And you can just trust that that will work. Of course, you can have them breaking changes once in a while, but at least they'll tell you. And let's you write JavaScript. Of course, you have the syntax of Angular to define a controller, to do the data binding
and all that kind of stuff. But, in the end, when you kind of just get that scaffolding stuff around everything, you write plain JavaScript within your controllers or within your services and everything. So you don't have the observable arrays, observables, computed, all that stuff.
You can just write plain JavaScript. And since this is a framework, there are concepts you have to learn, which is fine. There's not that many concepts, as we'll see after, that you need. So, enough about the comparison.
How can we transition from a knockout-heavy application? I'm talking about a web application that has maybe 20 to 50 to 100 knockout files, maybe even more. I mean, you have knockout all over the application. How can you get from that to Angular?
You could do that. How many would do that? So how many of you guys have ever been in a project and you thought, this is so crap? We have to just throw all the code out, and we have to start from scratch.
Any of you guys? Yeah? Yeah, I thought so. I've actually even written a spec for that, or, I mean, a project plan for that. Luckily, it never got started. That was way back when. This is obviously not a good idea. I mean, some people would say,
no, come on, let's do it. Let's wrestle with this ball of mud, which is our code. Maybe it's not a ball of mud. It could be a nice ball of mud. But still, in many cases, this is never a good idea. You'll probably be like this after a couple of weeks, thinking, shouldn't have done that. And, I mean, you will never get to this,
which is the shiny ball of gold where we want to end up, with a lot of beautiful Angular code. And so rewriting is never a good idea. I mean, you can think, try to put yourself in your customer's place,
being the chief architect or the boss or whatever who makes decisions. And one of the consultants comes in and he says, hey, guy, we need six months. We're going to give you zero new features. We're going to sit here and develop every day. You're going to pay for it,
and you won't notice anything different with your project. Is that okay? I don't think so. So that is obviously not the way to do it. What you want to do is something that I first heard when I was on Udi Dahan's course, and he talked about a method he called scavenging.
Now Udi Dahan talks about rewriting huge applications, like the service architecture and service bus-ish. So, of course, that's a different level of doing this. That's many years in the making. But still, we can adopt this concept of scavenging.
What you want to do is you want to pick small pieces of knockout code, the smallest piece possible, and you want to start with that. And you want to make that into Angular, and you want to do this slowly. And preferably, you want to combine it with a task you're already doing.
Let's say you're tasked with doing a new feature or maybe improving an existing feature in the web application. Grab that opportunity and just make it into Angular, get that improvement done, and that will be the best way to start. Of course, you don't want to do this under the radar.
You want to get some kind of acceptance for doing this kind of job. We're not tricking our customers. That's not the point of this. And the best way to do that is to go for quick wins. Something that improves either, in the beginning, this is okay,
improving the code base. Because in the end, you really want to get your team on board. You want to show your team, if they're not already like Angular fanboys, like me, you kind of want to get them on board and show them what you can do with Angular and how that will improve the code base,
improve the way we develop new features, and kind of just improve everything. And if you're able to do this, improve your code base, and also provide some new features to the website, that will also help you convince your customer that this is a good idea. And third, if you manage to do this
and not spend a whole lot extra time on the feature you're actually doing, that's the best. And that is what you want to try to achieve. So start small and don't be afraid to turn around. Nor will we have these mountaineer guidelines.
And rule number eight is always turn in time. And I think that's a good lesson here. Don't be afraid to just say, okay, this is too much work. I can't get this done in Angular, so let's just leave it and find something else to try later on.
Now, the fastest way to get started with Angular in an application is just do this. You create an app.js or something. That's the main Angular piece of code. Define a module. I'll go more into detail after when I go into code.
And then if you do MVC web applications, you probably have a layout.cs.html, so you can just put in the script references to Angular and the application.js and bootstrap the body, for instance, with the application, with the module.
This makes sure Angular knows that, okay, this is an Angular application. And this is not intrusive. This will not conflict with your knockout applications. This will work just fine, even though you have knockout all over your application. This is the fastest way to get started. And now, after we've done this, just start writing Angular code,
and it will start working, as I will show you after. And this is probably a nice start. You can do this. You can show it to your team, because, as I said, team, that's the key. You have to get your team on board. You have to show them how easy this is,
how more structure you get from your code. So, with that, I'm going to spend probably most of the talk showing some code. If you have any questions while I do this, please just raise your hand, and if I see your hand, I'll talk to you.
Don't be afraid. No questions are stupid, and my answers might be, but the questions are surely not. Let's switch over to some Visual Studio.
Now, I tried to find an open source knockout application that I could just rip apart, but it seems to be hard to find. So, I ended up just writing a quick demo application myself. So, some sort of movie site. Could be a...
Maybe it's a video on demand, or rent the movie, or maybe it's just your personal video, DVD collection, or something like that. Either way, you have the home screen, which displays some movies. You can go into the details. Not many details, but you have the genres, you have the title. You can search. So, for instance, search for Matrix,
and get some results. And we can add a new movie. So, we add Edge of... Of course, this is... This is not random why I picked that movie, but we'll see that after. Adventure, maybe?
I don't know. Haven't seen it. There we go. Edge of Tomorrow, with the genres. So, let's say we get a request. We get a feature request. This front page shows five movies right now. Let's say the customer wants us to change this.
So, they want us to display all the movies, and maybe with some buttons to filter on genres. And I'm thinking, sure, we can do that. We could do it in Knockout. Let's take a look at the code first. So, this is the view.
If you've all worked with Knockout, this should be pretty familiar, but I'll step right through it. We have the... Is the code big enough? Do you all see? Yeah? Good. Let me know if it's too small. So, we have an unordered list, which, for each,
some movies array on our view model. There's some visibility toggling here, if it's loading. And then there's a link that creates a link to the details page with the attribute data binding. And we have the poster, which is similar.
We use the attribute binding to set the source and bind up the title. And in the bottom, we wire up the view model with this top five view model JS, and we apply the bindings to the element top five.
So, this is... I don't know about you, but this is how I usually write my Knockout code. I bind it to a specific element instead of the entire page, usually. Let's take a look at the code, the JavaScript. So, it is in top five view model.
Here's the view model. Let's see what's going on. There's not much going on here. It's a pretty simple view model. We have the all too familiar of ourself is this. And then we have an observable array. We have something is loading. And we have a get,
which just goes down to the API takes five. So, the API is pretty simple. If you don't pass in the take, it will just return everything. So, that's nice to know. We set the movies on success, and we set the loading to false. So, if we go back to the view,
that means that this is supposed to only be visible when it's not loading. So, we don't get the toggling and non-bound items on our view. So, I'm looking at this, and I'm thinking, this is probably a good place to start because it's a small piece of code. And hopefully, it will be a small piece of code
to just get the exact same functionality with Angular. So, let's try that. I've cheated a bit. So, I've already added reference to Angular here. And also, I made the app.js. I'll show you the app.js.
How many of you guys have done Angular developments? Okay, not so many. So, that's good. I'll talk around the code a little bit then. So, Angular is built around modules. Everything is modularized. You have modules for everything.
And you have a couple of other concepts like controllers and services, which we'll look at later. But to start an application, you need a main module. You need the application module. And that is where everything else is kind of hooked on, chained on the main module.
And you define it by just doing Angular. If you reference AngularJS, you'll get this Angular keyword. And you say, I want a module. Its name is going to be, in this case, movies. And these magical square brackets tell us that this is a new module.
These are important, because I've mis-stepped here as well. This is actually where you place your dependencies. If you need to depend on other modules, let's say we pull in the routing module for Angular, we would actually have to say,
you are going to depend on the ng-route module. Because, in essence, what's in the Angular route.js file is Angular module, and then we have ng-routes.
And then all the code goes in some function in here. Of course, that's not something we have to worry about, but... And since that is a module, any other module can now take a dependency on that module. And with the dependency, you get all the code that is then hooked on this ng-route module.
I'm not going to use routing here, because this is a multi-page application. I'm going to show you some other cool stuff. Now, the importance here is that if I omit this, I'm just asking Angular for this module. Give me that module.
If it's not created, this will fail. If that module does not exist, this will not work. So that's the first thing I have to do. And it's the only thing I have to do to get the Angular application up and running. Now that I have my module, we can look back at our layout.cshtml, and this is the directive, they call them.
This little attribute here is what they call a directive. We'll talk about that more also. But the ng-app tells Angular that take control over my DOM, or take control over this part of the DOM. I could just as well just put the ng-app stuff right here,
and now everything that is rendered within this div will be under Angular control. So in some cases, you might want to do that. I could do that right here. But for demo purposes, I'm going to put it on the body, and that's normally what you would do anyway,
because you might need some navigation that is bound to Angular and stuff like that, which is outside the main part of your application. So let's go back to our view model and start to think about writing this into Angular.
Now, there's a couple of other things I want to look at, because when you look for best practices on Angular, you will get a bunch of different stuff. I mean, even a simple thing like how do I structure my Angular application will give you a bunch of different answers.
And there are projects on GitHub like the I think it's, I don't remember, AngularSeed, which is the first kind of this is how you would structure your Angular application. Don't use that. There's an AngularSeed enterprise.
Don't use that. There are so many things that they will never fit exactly to your project. So just try to think about how easy will it be to maintain our code, how easy will it be to locate our code, and how easy will it be to identify features.
So I've actually decided to go for an approach where I put the JS files in the view folder. So I'm going to make a kind of a movie list that goes on the home page. So why not just put it right next to the actual index HTML
where it belongs. That's where it belongs anyway. So I'm using ReSharper. I don't know if you do. So in ReSharper you can make these templates, which I love. So I'm going to make a movie list controller.
And boom, there we go. Movies. Now, here you see I'm omitting the square brackets. So I'm actually asking for the movies module. Give me the movies module because I have something that I want to attach to that module.
And in this case, it's a controller. Now, in Angular, as opposed to Knockout, we have more concrete concepts. So in order to communicate with a view, you need a controller. So it's a controller in the Angular context.
The name controller is used for so many different things in development. So just forget that. And this is a controller. And that is responsible for orchestrating your view. And I'm not talking about doing some jQuery element that hides show.
It's facilitating the data to the view. And the view itself will orchestrate how it displays data. Much like Knockout, really. But in Knockout, I've seen a lot of view models riddled with jQuery references and all kinds of stuff. Basically, you'll never do this in a controller.
Never, ever. As a matter of fact, if you start on a Greenfield Angular project, just don't reference jQuery at all because you won't need it. You'll never need it. Just a small secret there. Angular is actually bundled with jQuery Lite.
So you get some features and some stuff that Angular needs to do DOM manipulation. But you don't have to think about jQuery when you do this. So let's look at the syntax here. Because we define the controller and we give it a name. So I named it movelist, which would be weird
since it's a movie list. This is a movie list. And the next part is the square brackets again. And we recognize these from the module definition. These are the dependencies. And now we're no longer taking dependencies on modules, but we're taking dependencies on other services that we define.
And if I get the time, I will make a service and you'll see how that works. But for now, I'm taking one dependency by default in my template. You don't need to take any dependencies. You can just do like this. And that'll be fine.
But as you will see, the scope is quite important. Because in Angular, the scope is where everything that is displayed in the view will be. So if you need some data to be displayed in the view, you have to attach it to the scope. Angular creates scopes all over the place.
So you don't have to think about the management of the scope. You just have to pull it into your controller and start adding stuff to it. And in this case, if we go back to this, we need the movies list. And that's pretty much all the data.
So I'm going to show you we don't really need this anymore. And so what I do is scope.movies equals empty array. That's it. I don't need any observables. Because Angular knows that everything on the scope is potentially something that can change.
So let's just watch it and see what happens. And if it changes, we'll update the DOM for you. Don't worry. And if something changes in the DOM, we'll update the variable in the controller for you. And that's pretty simple. But we need some data here. And as I told you, the Angular core comes with an HTTP service already in it.
And the way we reference this is to take it as a dependency. Once again, dependency injection is default in the core. And this little dollar sign indicates that this is every Angular service
that you can take a dependency on is prefixed with a dollar so that you can separate them from your own services and your own stuff that you make. So we're going to take a reference to HTTP and put it in here. And by now, you're probably wondering, why is he doing this and this?
And there's a good reason for that, unfortunately. And it has to do with minifiers. Because actually, if you look at the examples on Angular sites and tutorials, they actually do something like this when they define a controller.
So move a list, and then you just have a function with the names. And this will actually work, because Angular will just look at these arguments and say, OK, he needs a scope, he needs the HTTP service, so I'll just inject them. Can anyone of you think what happens if I minify this code with a minifier?
If I minify it, a lot of things will happen. One of them is this. Now, Angular has no way of knowing that A is supposed to be scope and B is supposed to be HTTP. So this will break your entire application.
So in order to fix that, one of the things Angular has done is to make this syntax like this so that I specify the dependencies as strings first, and then the order of these strings are injected into the function.
So in this case, scope will be A and HTTP will be B. Name your parameters wisely, so the minifier can do the rest. So I'm going to stick with scope and HTTP, which is a good practice. Now, there's a way around this, because Angular has actually made their own minifier.
So that's a minifier running on Node.js and stuff like that. I haven't tried it that much myself, but it will actually minify it correctly even without this stuff by parsing the JavaScript actually with regex and stuff like that before it minifies it.
But it's good practice to use this, and this is an MVC application. I'm using the bundling that comes with MVC, so it will minify the code for me, and this will work just fine with the built-in minification in MVC. So enough about that. I know they are working on some huge changes to how this dependency injection works in version 2,
so maybe this will all change by then. I don't know. So let's get on with this. I need some data into my movies array, and let's just cheat and get the URL right here. So the feature request was that all movies should be returned, so the URL would be this.
Now, I can do HTTP, and HTTP has kind of a few different syntaxes. I could pass in an object-elect role where I do gets as the method and stuff like that,
but they made short hands, so I can actually just do gets, HTTP gets the URL, and if I need more parameters, I can pass in data and stuff like that. And the HTTP service uses promises.
How many of you have worked with promises in JavaScript? Yeah, good. So some of you know. A promise is basically you pass in something that needs to be done, and the promise says, okay, I promise I'll do it, and when I'm done, I'm going to tell you. And that is basically what happens here. And instead of passing in the function like you would do in jQuery, we're going to chain it.
So once this returns success, we get a function that has a result. And the result will be the exact result from your controller. So in this case, it's an array of movies.
So I can just say scope.movies equals result. And that is pretty much it. That's what we need. So that's not too bad. It looks pretty much the same, but we have gotten rid of one dependency, and that is the jQuery dependency.
We no longer need that in the actual controller. And, of course, this is a huge advantage when it comes to testing. I don't have time to go into testing today, but there are a lot of good blog posts on testing Angular, because when you test Angular with Jasmine, you can mock up all these dependencies.
So you can actually mock up the HTTP or just put a spy on it. Say an HTTP service should have been called with GET and so on, and return some mock data. So that makes it much easier. Now, we've done this. Let's go back to the view. We need to rewrite the view.
So I'm going to keep them side by side. So I'm just going to copy this up here instead of changing it. I'm going to copy it, and we're going to look at the differences in how you bind stuff in Angular. Whereas Knockout is very data bind attribute heavy. Knockout does not do that.
In Knockout, you have separate attributes. Or they call them directives, because that's what they are in the Angular code. But we look at them as attributes on our DOM elements. And I must say I like that better, because these things can quickly grow out of proportion,
and be kind of hard to read. So in order to do this, we have to do it slightly differently, because the for each or repeat in Angular does not repeat the contents of the tag, which Knockout does.
It actually repeats the element itself. So we have to move this and put it down here instead. And we're going to use this. All the directives that you get with Angular start with ng. And that is because ng is kind of Angular.
That's how they justify that. And then which is good. And ng-repeat works like a for each loop in C Sharp, for example. So you can just do for each movie in movies. And this will just iterate every movie that is in movies.
And of course I could call this whatever I want, but I like good naming. This is the first advantage in Angular, in terms of binding. Because down here, it's not explicit what title is.
You don't really know what title is directly. But when I bind up this in Angular, I have to actually specify it with the movie. I have to prefix it with movie. So in this case, I don't need this anymore. Because in Angular, you don't have a separate attribute for just the text binding.
You can basically just do the curly braces, movie.title. And this will now render out the title for the movie. So I no longer need all these spans to be able to show text from the view model on the view.
The link, I can use something called href. This will actually hijack the entire A element.
Because sometimes if stuff doesn't bind in time, you'll get an A that has either a blank or maybe just a hashbang URL if you assign the hashbang. If you don't assign anything in href, the link will not look like a link until it actually has an href.
So the ng href takes care of that for us and makes sure it looks like a link and gets the data set in href. So in the ng href, I can just take the URL down here.
Let's see if this works. And movie.title. This is not quite correct because now I need the curly braces. I can do like that. This will now be a hyperlink with the URL and the title in line here.
Now, once again, this is opinionated. I like the curly braces syntax. I know a lot of people who don't like them. Like some more proper, regular text instead of messing up the DOM with a lot of curly braces.
But it's not that messy. I think it's okay. Let's move on to the picture. The poster can be done in the same way. ng source. You can actually do exactly the same thing here. I don't quite understand why this has to be so bloated with knockout.
When you can just do it simple like Angular. I'm sorry. I know Steve Sanderson is somewhere in the conference. I should be careful with what I say.
He might come beat me up. Now, this should be it. Actually, no. Almost. There we go. Well, thanks.
I don't need this ID anymore. Because now I'm going to pull in the reference to our movie list right here. And I'm going to wire this up to our controller. So knockout requires this line somewhere in your code.
You don't have to have it in the view. You can have it in your view model or wherever. With Angular, we use a similar approach as we did with the ng app. We do ng controller equals movie list.
Now we tell Angular that everything inside here is being controlled by the controller movie list. And this is the controller movie list. And I see a lot of tutorials and blog posts where this is written. Maybe you define it like this. Movie list controller or movie list CTRL or whatever.
Personally, I don't like that because this already tells us this is controller. So it's kind of redundant to have controller in the name as well. And also, we write the same thing here. The controller is movie list.
So why do we need to write controller in here? And why abbreviate it? So I just make them the actual name. Write them the actual name. And that should work. Let's just cross our fingers and comment out the knockout code because we don't need it anymore.
Let's see how this works. These are long seconds. Let's see. Nothing. Ah, there we go. So if you noticed, we had a little...
Oh, we don't see it anymore. We had a little curly braces and movie title. And you can actually fix that by doing ng cloak. Just put that on whatever you're binding. And it will kind of take care of that jumping little text so it makes sure it doesn't show.
But this is locally, so it's kind of hard to show. But now, we're not done with the feature yet. I have 15 minutes left, so let's hope I can get this done. The feature request was that we were supposed to be able to filter these on genres.
Now, we already have genres, so on the object, let's just see how everything works. We have the genres. Let's see if we can make a nice little button tab thing here where we can click on one genre and show only movies within that genre.
That should be fairly easy. I mean, it probably wouldn't be that hard in knockout either. But if we step back a little and think, how would we do this in knockout? We would probably have some property that holds the click genre.
And we would need a computed property that actually filters the movie list and only returns whatever movies are in that genre. We would need some placeholders and separate stuff in here. In Angular, we actually don't need that.
The only thing we need is some way of toggling a genre and knowing what's the current selected genre. So let's just make that property right away. Selected genre, and let's leave it empty. And we need a function. This is similar as in knockout.
If you need a function that you need to call from the view, you define it on self in knockout. You define it on scope in Angular. So toggle genre, and that's a function that takes... I don't know why it does that. It takes a string.
And let's just make sure this actually toggles. So if scope selected genre will just empty it, and in the end selected genre equals genre.
Now this will... If we get action, and action is already set, it will blank it out and set this to blank. Otherwise it will actually set the correct genre to selected genre. Now in order to hook this up, of course we need a list of genres,
of the unique genres in the movie list. For that, of course, Angular is not filled up with all kinds of array functions or whatever, so you need some separate utility library for that. I've chosen to use lodash. I don't know if you know the library lodash.
Do you know underscore? Underscore? Someone? Yeah, maybe. So it's actually quite funny, because lodash is actually an underscore. So they just say, we made it just better. And I kind of agree, I haven't used it much. I've used underscore most of the time, but I looked at lodash and I thought that's fine.
So we need some array scope.genres that we can display in the DOM, and we need to fill it. And I'm going to show you real quick how easy that is with lodash. Now this is not Angular magic, this is lodash magic.
So I would do scope movies, and I say chain, because lodash gives you the opportunity to chain stuff, chain a lot of different operations. So I say, take this array and first flatten,
give me all the genres, flat. So if I just... This is a shortcut to something called pluck, where you can do, in this array of objects, pluck this property from each array, each array item. And this actually says,
pluck all the properties called genres, give me them and flatten them, because the property is an array. So I just need a flat, big array of all the genres. So flatten will give me the genres, and then I can just do unique and value, and that's it.
Now I will take the entire array of movies, pull out all the genres, flatten them to a list, and get distinct values from that list, all in one chained little thing. Let's do it nicely like that. And they have lodashes, all sorts of other stuff you can do.
First, sort by, whatever. Check out their site. Just Google lodash and you'll find it. Now we have a genres array, which is filled when I get the result from the HTTP GET. So now we can wire this up in the view. I need to move a little quickly,
because we're running out of time. I think I'm going to make this before time runs out, actually. So, I actually have made a class called GenreLists and class GenreListsItem, and I think I made it like that,
so I cheated. Boo. And I have to bind this up with an AngularNG repeat, so I have to repeat over all the genres. Repeat equals genre in genres. That's a hard word to say.
Now we have the... Let's just close the knockout thing. I'm in the movie list, the genres are filled, and I bind it, and let's see how that looks. There we go. We have all the distinct genres in this list.
Now we need to filter on this. We need to be able to click these, and we can do that pretty simple by just putting an ng-click equals toggle genre and genre. Now this, you would think this would work,
but actually this is like knockout. The toggle genre is not defined on the inner scope of this repeat, so I have to do parent dot toggle genre. I do think. So, let's just see if that works.
No, it didn't. Did I miss something? Did I call it something else? No, I did not. Let's put it on. There we go. This should work a little better.
Sorry, it does actually work, but I didn't tell it to set a class on the actual property. So, we can make it...
Let's say we have a selected class that we need to apply to the list element when it's the actual selected genre. We can do that with the ng-class. So, ng-class is a directive from Angular as well. It's not that different from how you do it in Knockout really.
You say the class selected should be set if selected genre equals genre. So now, if I go back to our site and that should actually work.
Let's see what's going on. This is always a fun part of demos. You never know. Maybe we'll get some debugging tips as well. So, let's just see if this is actually toggled at all. I didn't have to refresh. Yep, look at that.
It's completely misspelled. Let's just copy and paste to make sure it's correct. There we go. Went into the code and it looks nice.
Okay. So, now we're able to almost... Yeah, we're able to click the genres, but the list is not filtered. So, this is where the computed would come in, in Angular. No, in Knockout, sorry.
In Angular, we have, I would say, a slightly better way of doing it. I could now pipe this. Pipe is something you do in Angular when you have something called a filter. So, what happens here, if I do like this
and say selected genre, this will use something called filter, which is built in in Angular. We'll take the array and we'll pass it into the filter function
and it will actually look for any items that has selected genre somewhere in them. So, in this case, if I select action, it will return a new list that only contains the items that has action somewhere on the JSON object. Let's see if that works out of the box.
Here we go. That's all you need. So, now we have a filtered list. There are a bunch of other filters and you can make your own. I wish I had some more time, but I'm kind of running out of time.
I have six minutes left. There's one... Yeah. Let's just show a quick example without really doing anything. We could... Let's say we need to show how many movies are returned. So, we can do something like this.
Div, ng... Yeah, let's just do like that. So, we can actually use this filter wherever we want. Let's see. Hang on.
I'm just thinking, let's just show this right here. Pluralize. Count. I'm going to talk you through it after.
So, movies. I think this is going to work, isn't it? Maybe not. This is not going to work. The hat is in my head.
All right. Let's just illustrate it. Let's say we had a count thing here. Not two. Like that. And now you can actually say zero and no results.
One. One result. Sorry, one result. And other results.
Let's see if that works out of the box. So, this is not actually counting the items. But this is also a built-in. And this is what I like about Angular. They've taken all these kinds of things that we write over and over and over and over again.
And they just made something built-in for it. So, in this case, they made a directive called ng-pluralize that if you hook this on an existing element, you also put on the attribute count and when. So, count can be bound to something on your model.
So, some kind of results.length or something like that. For example, movies.length. Like that. And when it renders out the text, it will look at the when object literal. The object you have in here.
And we'll see, okay, so we have zero. Then we write zero results. If we have one, we write one result. And anything else, we just write the number. This is a placeholder for the actual number that is in counts and results. So, in other words, you don't have to use the parenthesis s in results
or you don't have to parse it yourself. You just have a reusable directive. And I guess this should be... Yeah, it didn't show up here. Let's see. Am I not doing it right?
Yeah, there we go. So, six results. This, of course, does not work now because it's not filtered. Now, I'm going to just mention one more. I have two minutes left. For instance, there's another directive that... Let's say I had a form input. For example, the form that adds a new movie.
I really wanted to do that as well, but I don't have the time. Here we have just a regular text box that takes a comma-separated list of genres. And it actually...
does some magic with the computed on the view model. Splits it, makes it into an array, trims all the strings and all that. If you had that in Angular, you could actually just put on the directive ng-list. That would make Angular take whatever you write into the box, split it on comma and return an array for you.
Because that's usually what you want when you do something comma separated in a textbox. And ng-list is all you need and the property bound on the scope will then get an array instead of a text. And the same goes the other way. If you pass in an array on your scope, it will be rendered as a comma separated list. So it just works.
And it's easy and there are so many... If you go on Angular's site and just go through the API and look at all these built-in things, you'll be, wow, why didn't anyone do this before? They even have a directive to pull out all the links and email addresses from the text. I mean, it's brilliant.
So there's a lot of nice little features in Angular. Unfortunately, this is all I managed to do in an hour. But I think it's pretty good. We've introduced Angular. We've gotten some feature going. And I do think if you show this code to your team,
they might be impressed in how easy it is to do stuff like this. Do stuff, manipulate the DOM. I haven't used jQuery a single time. And the layout looks pretty much the same. And it's easy to read. And I think we maybe have time for a quick question, maybe?
Or two? Any questions? Ah, there's one. So the question is, do I use Angular in everything I do? No, I don't. I still work on projects where we use Knockout. But we have decided that Angular will be the framework of choice for new projects.
And of course, everything I do privately, I use Angular for.
No, I have not. So the question was, have I tried to do this with any other frameworks like Durandal or something like that? I have not. But I would think that the approach would work anyway. And pull things out into services, make things reusable modules. And you're going to go a long way.
Any more questions? Yep. Oh, that's an interesting one. How does Angular keep track of the values when they're not functions? Well, the secret lies in the scope service that you inject.
Because the scope service actually has methods for always knowing what's going on. When you set a value on it, it will run a... Look, I just set a value on myself. Update everything that needs to be updated. So everything that happens on the scope value, the scope property or service,
will be pushed out into all the different scopes. So the scope is really the key in everything you do in Angular. But you don't have to think about it. Anything else? No?
Okay, thank you so much for coming. And please remember to put a green note in the... And thank you. Enjoy the rest of the conference.