 Our next speaker is a full-stack web developer, formerly a graduate student of economics and finance. He discovered his passion for programming and hasn't really looked back. And he's currently focusing on client side, model view controller, and data visualization. And it's tackling the big challenge of how to merge the two, and it has taken on the huge challenge of trying to help us understand how to work across different web technologies and data visualization. So please help me welcome Sam Selleckopf. I've been working with D3 for, I don't know, for about a year, a year and a half. And during that time, I've experimented with all three frameworks just in my work and in my free time. So this talk is really about telling you what I wish I would have known when I started, kind of what I've learned. And there's a lot to it, and I'm going to try to cover, I mean, obviously this topic is a big scope, so I'm not going to be able to cover everything. But hopefully, I give you enough information that you feel comfortable looking at it yourself and kind of taking a dive into how these technologies work together. So why frameworks? Why do they exist? Well, JavaScript applications are becoming more complex. And even though the frameworks all do slightly different things, they're really about providing your application with some architecture. Now, every application has an architecture, even if it's not explicit. The goal of the frameworks to varying degrees is to make your application architecture more explicit and help you avoid making costly mistakes. Architectural mistakes tend to be worse as your application grows in complexity and size. So that's essentially the goal of all these frameworks and others that we're not talking about today, is to paint you into enough of a box that you don't hang yourself later on down the road. So that's essentially why we're interested in frameworks at all. So let's see if we can make this bigger. The web, it's wonderful. I think we could all agree that this is an example of bad code. So it's not zooming as much. But essentially, this is just some jQuery that is doing a lot of different things. And I don't know about you, but I definitely am guilty of writing code like this, especially when I was starting out. So this is adopted from a talk by branding keepers from GitHub. But why would we say that maybe this is bad? Well, it's because there's a lot of concerns that are being mixed here. There is a page event being dealt with. There's network IO. There's a user event being handled. There's user input being read. Another network event. And there's HTML templating going on. So this code kind of mixes concerns. Now, if we were using Backbone, instead of querying the DOM for the data, we might store the data in a model. That's one of the main layers that Backbone provides to prevent you from writing this kind of code. And if we were using Angular, we could use a directive to encapsulate a templating portion of some chunk of our GUI and keep it separate. And in Ember, instead of making these kind of ad hoc AJAX requests, we could use a route. One of the main purposes of routes in Ember is to provide you with an object that is responsible for getting the data from the server. And so all the frameworks have solutions and varying degrees, primitives that they give you, objects, roles that help you avoid these architectural mistakes, which cost you more and more as your application grows. Now, of course, in web development, like in any area of life, there ain't no such thing as a free lunch. So using a framework has costs as well as benefits. The primary cost of using a framework is learning the framework's abstractions. And this is a non-trivial endeavor, especially the frameworks that have a larger surface area. It takes time to understand how they work. And to really get the benefit of using a framework, you have to take that time and understand where the framework authors are coming from. Because if you don't and you try to write code that you understand within the context of the framework, it's not going to work out very well. It's going to be difficult. You're going to be missing out on the benefits of the framework. You'll be fighting the framework instead of using its benefits. So you kind of start to learn to think in terms of the framework for the common pieces of your applications. You still have a separate layer for your domain. But the common things across all your applications you think of in terms of the primitives that the framework gives you. And there's a lot of benefits. So even though there are costs, and this is difficult, to learn the framework sometimes, a growing number of people, I think, would say, are being convinced that it's worth it, right? That the benefits we get from sharing ideas and promoting best practices help us to create applications that are more robust and to create applications quicker and avoid those architectural mistakes. So where does D3 fit into all this? Well, data visualization in the web is becoming much more prominent. There's companies like Square, LocalLytics, Chara.io, Plotly, Adapar who feature visualizations as the primary value of their application. It's not just a small piece of it anymore. And when this happens, when D3 becomes more prominent in the app, the amount of D3 code goes up and it becomes complex itself. And so it becomes more important to understand how to fit our D3 code in with our application architecture, regardless if we're using a framework or not. But as we use the frameworks, which people are telling you to do because applications are becoming more complex, it's important to understand how they fit together. Now, the ecosystem, the D3 ecosystem, as I'm sure everyone in this room is aware, is excellent for learning, especially for learning the framework, right? Because you go to d3.com and you see a huge list of examples. And you can click on anyone and you can see the code and you can dive right in. But when we're building complex applications, we're building object-oriented systems, typically, right? And so going to an example page and copying it and pasting it into your application doesn't really scale and it doesn't really fit into the paradigm in which you're writing the rest of your application. So our applications tend to be object-oriented, but a lot of D3 that we start out with, that we share through the examples and as we're learning, tends to be a set of steps on how to reproduce a particular visualization. It's a procedure on how to produce this thing. And so what's important is to bring those ideas together, to make our D3 code object-oriented. So it's just as reusable as the other pieces of the other primitives that we're using in our application, all the other pieces of our system. And so essentially what we're doing is encapsulating our D3 code in objects, integrating it with the rest of our application. And if you're using a framework, you want to think of the framework's primitives, the architecture that the framework is promoting, so you see how your D3 code fits in. And you want to embrace those idioms. Essentially, we want to take the lessons we're learning from the frameworks. And it's not just about these three frameworks. It's about the bigger discussion of building complex JavaScript applications, right? This is new for everybody. And we're all learning how to do this. And we essentially don't want to miss out on these lessons when we're building really complex apps that feature a lot of D3. Now, I'm not saying we have to marry our D3 code to the framework, right? If you're making a backbone app or an Angular app, it's not like all the D3 work you write is now tied to the framework. It doesn't have to be. The approach that I've taken over the last year or so is to treat them essentially completely separately. And that's because even though D3 fits into the rest of our system and it has its role, it's kind of, it is different enough that we want to be able to share our visualizations. We want to be able to reuse them. We don't know if what we're using here we're going to want to use somewhere else. It probably is because these charts tend to be reusable, right? They tend to apply to many different situations. So it's not about having a high coupling between your D3 code and the framework itself. So if you're worried about that, you don't need to be. Essentially, again, the lesson is we want to take what we're learning from the frameworks and treat our D3 code as first class objects in our system, give them roles within the rest of our system just like we're giving roles to every other piece of our system. OK, so why are we talking about these three frameworks today? There's a lot of others, and this is not a statement about which is the best framework. I think these three frameworks are sufficiently popular. I think most people know about them. But they're also sufficiently different from each other. Again, the purpose of them is to help your applications architecture, but they have different perspectives on this, and they do so to varying degrees. So they're different enough that they provide a good illustration for us to see how we can incorporate D3 into different types of applications. So in all three frameworks, D3 has the most. So these are MVC frameworks. Not to be, I don't want to get pedantic or anything, but they all attempt to separate the data into a model layer and the view, the actual GUI portion of your application into a view layer, and then there's something in between. D3 has to do most with the view layer in MVC. And so for the rest of this talk, we're actually going to be building up a chart to use with all the frameworks. And each framework will influence our thinking about the chart as an object, and the framework will influence the public API that we're giving to our chart. OK, so let's say we work for a company and we want to help our CEO understand where his revenues are coming from and the breakdown of his revenues and costs. And he has lots of different clients, maybe different customers that he sells to. So we go to D3 org and we browse examples and we see this cool looking bubble chart and we say, well, that would be useful. Maybe the area can code the value of the revenue and the cost. And so this is what we start with. The example shows us it's just this 50 line procedure and we can just copy and paste this in and we get the chart. So this is what we do. So the code right here is what we're looking at in the browser. And I've just included D3. This is literally the same procedure from the site, with the exception that instead of the data that was on the site, we have this companies.json. Oh, yes, sorry. Yep. Sorry, there's this giant monitor here and I was like, oh, that looks great for everyone, right? It's like, this is nice. So let me go back. All right, better? And we're in the backseat? Awesome. So this is all static files. And so there's no magic, nothing happening here, special. And I'm just including D3 and then this is the procedure. And the only thing I've changed is right here, I'm pointing to companies. And that's this file right here. So we've got Wayne Enterprises, we've got Sark Industries. This is a pretty cool company that we're working for. Dunder Mifflin is not doing as well as some of the other ones. So this is really the difference, but this data is in the same format as the format we saw on the example. And so we swap it out and there it is. We refresh and that's the same code and we see it. So now we have a chart and that's awesome. So we just got it done. We can wipe our hands clean and pass it off. But the problem is everything, like I'm sure you all are aware when you're building applications in general, complexity goes up, new features come in and you need to build something that can scale. And so this is just the first solution. But we want to make it object oriented, right? That's the next step. And so instead of just copying, pasting procedures, we want to object orientize our chart, right? And in general, object oriented programming in JavaScript, there's two patterns. You can use prototypes or you can use closures with gettersetters. Mike has an article about the ladder because that's the pattern that the library D3 itself uses. And you can use a hybrid approach as well. So we'll be using the second approach in this talk. Now, because of the, there's some unique things about reusability in D3. And certainly JavaScript is enough to make reusable charts that are very modular and well organized, but it's difficult to do. It's not just an easy thing that you can throw together. So I would encourage you also to check out this library D3.chart from the focus of Boku, which is a library that's specifically built to help you build reusable charts. And again, if you were to use D3.chart to make reusable objects, all the work that you're doing could apply. The lessons I'm teaching today would apply to that chart because they're separate. And so it doesn't matter how you make a reusable chart object, the important point is that you do so that it's modular and can be extended and reused. And so for closures with gettersetters, the main idea here is to make a constructor function. And we have these three kind of areas that we break our procedure into. The first is we have configuration variables and other variables that represent D3's primitives like scales and axes. We have the actual function in the middle which generates the chart. That's where we write our D3 code. And then we're gonna return that function, the inner function, which will create a closure. And that's how we'll bind the function to those local variables. But because functions are objects in JavaScript, we can actually attach methods directly to this chart function. And that's how we create our gettersetters for these variables. And so essentially the bottom, the public methods, that's the API for our chart. When it comes time to incorporate the chart with our other code, our application code, this API is how we'll manipulate and configure our charts. And this is how we use the chart object. We just get some data and we instantiate it and we can set some config. And then we provide a D3 selection, a bound D3 selection with the data and then we call our chart. Dot call is a function in JavaScript that invokes a function. It's a method that invokes a function. So this is the same thing as calling the chart function, passing in a selection. But this lets us chain the pieces together. It makes it easier to do method chaining. And so that's it. And so we can look at it here. I won't go over it too much in detail. You can read the article for more information. But the main point is that now, instead of just reproducing the procedure, we're focused on making sure this thing is reusable. And so we separate all of our actions into the sub selections, enter, merge, exit. And so now we can add data and remove data and our chart is reusable. This is just, what's happening here is just, I'm just doing some set timeouts, but we see it's the same data being called. We're just changing the data. So the chart is being called in the same way. And this is basically how we have reusability. And so the object is self-contained and we can reuse it and extend it and configure it. And that promotes sharing throughout our application. All right, so let's talk about backbone. Backbone of the three is the most lightweight, but it has an idiom, certainly. At its heart, it's about providing you a model layer for your data and an event system, which lets you bind that model layer to the DOM, to your GUI. And so let's look at a simple example first. So here I have just backbone and its dependencies. And that's it. And here's, that's just for the demo at the end. So instead of just making AJAX call and passing in an array of JavaScript objects to our chart function, we wanna use what Backbone's given us, a collection, to store our data. And so that's the first step. We create a collection and this is the same data from before, from our JSON. But now it's in this collection and the collection gives us a place to write helper methods that we can use to transform the data. And it actually, instead of just wrapping these plain objects, it's creating backbone models. Right now, since we haven't specified what type of model, it's using the default model, but this also gives us a place we could redefine the backbone model to something we want and say give it a profit method, which would let us calculate the profit for each company. And so this is how we store the data. Second step, now that we have the data in a separate layer, we want to create a view to actually paint something to the screen. And so there's a view object, which is responsible for this. And all we have to do is extend the backbone view. And then we have an initialized function and there's two things that we do here. Essentially, we subscribe our collection, our view to changes on the collection. This is saying if any model in the collection changes or a model is added or removed, then we want to re-render the chart, or I'm sorry, the view. And then also we kick off an initial render when we instantiate this view. Okay, so what does it actually mean to render? Well, this is where we define a render function. And this is going to let us specify the HTML that's going to be rendered to the screen. And so here, this is a template. As your application gets more complex, people usually break out templates into separate files, but this is just a simple demo. And if you're familiar with Rails, the ERB templating syntax, this is something similar going on here. Underscore has a utility that lets us compile this template passing in a context and then it'll render it to the screen. And so we provide it with a template and then we set the elements to it, the inner HTML to that rendered template. But we still don't have anything on the screen yet. Right, nothing's being rendered. And that's because this is really just a class definition. We actually have to instantiate it, so that's the last step. So we instantiate our view that we've defined, giving it a DOM element and passing in the collection of companies that we defined earlier. And now we have a list. And this is our view, essentially. The view is managing the entire thing. Each one of these represents a backbone model. And add and remove company. Those are just buttons that push and remove elements. Companies, in this case, is just a global object, which represents, which is the collection. And so if we push it and remove companies, we can see the backbone event system at work. This is working for us automatically. I can even do this right here. We see companies and I can say at zero, destroy. So it's happening for us. We don't have to write any code to keep those in sync. Once we set up the, once we subscribe our view to the collection change events, it happens automatically. Okay, so that's the basics for backbone. Now let's bring in D3. And the only thing I've changed here, this is what we just started with, but we brought in our bubble chart. This is the reusable chart that we created. It's our object-oriented chart that we made, and we've imported that, and then D3 itself. So the first step here, I like to think of the data first. Just like when we were making the simple backbone app, we wanna think of where the data is gonna come from. It's gonna come from our collection, but the collection itself is a collection of backbone models. Our bubble chart doesn't know how to render our collection of backbone models. It needs data in a certain format. So that's precisely what the collection is good for it. It gives us a place to add transformation methods, and so we can just redefine, instead of using the default backbone collection, we can redefine it into our own collection, a company collection, and it has all the same basic methods as the backbone collection, except we have defined a custom transformation method that gives us the data that we need in the format that we expect. And so this here refers to the models, and so we can just map it, and just take the data we need, right? And so here when we instantiate it, instead we use our own collection that we've defined. And so the second step is to define our bubble chart view. We have the object, but we need to wrap it in a backbone view. And the idea here is, right, whatever charts we're rendering on our screen, they represent isolated chunks of our GUI, and in backbone, views are how you encapsulate those. And so that's what we wanna do. We wanna use the same thing in backbone that we would use to encapsulate other portions of our GUI to encapsulate our D3 code. So we create a bubble chart view. The initialize method is the same as our last view. The only difference is we have a chart property, which is our object, and then the render function, instead of setting the HTML of the element, we just call the chart. And now just like before, we actually have to instantiate this, right? And so we give it a DOM element, we pass it to the collection, and that's it. And if we change both the bubble chart and the list are subscribed, and so everything's working. That's all we had to do because the event system keeps it in sync. And so here we made our bubble chart in isolation and we added it to backbone and we're good to go. We can make other views that have different configurations. We can make a base bubble chart view and just only extend it into many different kinds that change small things. And so this is a really nice way to incorporate these two technologies. So really quick, some things to consider. Backbone doesn't have a lot of, the view layer is not much more than we looked at actually. It's the smallest part of backbone. And there's a lot of complicated issues that arise when you build a complex application that has to do with nested views and who's responsible for view instantiation and view cleanup. So as your application gets more complex, people tend to use libraries like MaryNet or Chaplin or Thorax to do this. And D3 can work with these technologies too just like we saw. Some patterns in backbone, a parent view would actually render a child view in memory and then append the child views HTML. In D3, we tend to use D3 with DOM elements that exist in the DOM before we start. So this pattern wouldn't work like we're used to it. Actually in D3, you can create fragments and generate the SVG in memory, but that's not how we tend to write D3 code. We usually have it exist in the DOM first. So in this case, you could have a separate method that will append an element to the DOM so that the bubble chart view itself can actually render. And then finally, even though it was simple to wire these two things together, we had to write the code that glues the view to the events that the collection is emitting. And again, there's complexities that arise as your application gets more complex. And so people sometimes use something like React or a different layer just for the V part of MVC when building backbone applications. And so this is something else to consider. So let's move on to Angular. So Angular, of the three frameworks, Angular kind of sits at the intersection. It has more primitives that come with it than what backbone gives, but it's certainly less opinionated than Ember. It's not as prescriptive. It's defined by the author actually describes it as a toolkit for building a framework for your application. So it's actually not trying to be a framework in the sense that like Rails is a framework, right? It's a toolkit that lets you build, provides you with abstractions to build your own framework for your application. Directives are similar to backbone views in that they're the object whose role is to manage portions of your GUI. And so that's what we'll use for our D3 code. Now surprisingly, there's no separate model layer in Angular like there is in backbone. There's no Angular model or Angular collection. Most, a lot of people use plain JavaScript objects and arrays to represent their models and collections, although you can bring in something else. Right, so let's get started. So here we've just brought in Angular itself and jQuery. jQuery is actually not a dependency for Angular, but it plays nice with it and it gives you a few more methods. Out of the box it comes with something like a jQuery light, but we want to use some, make sure we have all the selectors that jQuery offers. And so the first step is again, we think about where our data is gonna come from. We're not just gonna make an Ajax request here and paint it to the screen. It doesn't have a model layer per se. You can use objects and arrays as models, but what Angular provides are controllers to present the data in your model layer to the template. And so first we're gonna create a controller. And this controller we're calling it a company's controller. And when you create a controller, you pass an array of dependencies that you want that controller to have access to. Here we're passing in just the main dependency is scope and this is the scope that the controller makes available to the template. And the reason it's called scope is because it actually is a separate JavaScript scope. That's all it is. It's creating an isolated scope for this portion of the screen. And when we create a controller, we have to specify which part in the DOM we want that controller to control. And so we do that like this. We kick off our app with ng-app. This is actually a directive. This is how you use directives. You put them in the template. And then we specify that the controller is responsible for this div element. And so then we just attach our companies to the scope. And that will let the controller make that, those company objects available to our template. And so then once it's available, we actually want to render it. And we do something similar that we did in Backbone except we use ng-repeat, this directive ng-repeat instead of compiling a template with each in it. And so we're saying for each C in companies, we want to print the name and the revenue. And it has companies because our controller is made available in scope. And so let's look at this. Yep. Yep. So right now there's only, this is essentially all the HTML. And it's just the demo and the company's controller. And so this is nested in here so it has access to companies. And that's it. What you see right there, our companies are being rendered. So that was pretty simple. Now, step four, let's add a filter. So this ng-repeat directive that comes with Angular out of the box lets you kind of do Unix style piping. And so we can actually just pipe it through a filter. And then let's say we want to filter for Mithlin. We want to see how guys that the office are doing. And so now it renders only to under Mithlin, right? But we don't really want to hard code this filter. That's not very useful. So instead we'll create a search box. And the search box is just an input element in HTML. The only difference is we are using now this ng-model directive. And like I said, it doesn't have a model layer in the sense that it doesn't provide you with objects to wrap your models and collections in. Model means what the scope is pointing to, essentially. That's what model means. And so here we're creating a new model on our scope called query. It's the same thing as if we came down to our controller and wrote scope.query equals something, right? That's exactly the same thing. And so here we already see one of the differences is that Angular provides you with data binding between your template and your scope declaratively, right? You just declare this is where I want this data to be. And if we change the input here, then Angular will automatically sync the query variable on our scope to whatever the user's typing. And it's actually two ways. So if some other piece of our GUI changes what the query is on the scope, the input field will update in the DOM to represent that. And so that's one of the main differences here. We're using the template layer itself to declare our bindings instead of writing the event handlers manually. And so this creates this search box and we can type, and I promise you it's changing the scope, it's just we don't see that. And why don't we see that? Because we're not displaying this query anywhere. Well, let's just filter based on the query instead of the string. And so now if we type, we see it filters, right? So that was pretty easy also. What's the next step is to, we want instead of hard coding in the revenue, we want the user to be able to change revenue and cost, right? So we create a radio input, we bind these two radio buttons right here, revenue and cost to the same model, selected item. This creates another item on the scope. And so now we have a selected item that represents whether the user's clicked revenue or cost. And so we want to just show what the selected item is instead of hard coding in revenue. And so we'll show it like this. And there's no initial value. So we can come down to our scope and set an initial value, revenue. And so now we have revenue and we have cost. Again, we're using this declarative template to specify to wire together our DOM and everything still works just as we expect. So that's very basic to Angular. Now let's look at, let me make sure it's the basics. No, we got one more step. That step is to talk about a directive. And so this app is small enough where we wouldn't normally break out this portion of our GUI into a directive, but I want to explain it in the context of a simple application so you understand. A directive is essentially what backbone view is, although for simple things, you don't need a view object as we've seen. A directive encapsulates a portion of your GUI and lets you add behavior to it and it does some other neat things. So let's look at it. To make a directive, we just create using the .directive function which is off of our main module. We give it a name and then we have some options here when we return their actual directive. The first one is restrict. We are gonna make this directive element restricted which just means the way we use this directive is with a tag in our DOM as opposed to an attribute like ngapp. Here's a template and this is literally, this is exactly the same DOM as what we had above. So we're just specifying it as a string here. Again, when your app gets complicated, you can break these out into separate files. And then this is interesting. So this unsurprisingly, will create a new scope for our directive. And so now when we're rendering the directive in our template, it has its own JavaScript scope and so it doesn't by default have access to the surrounding scope. So our controller is controlling this portion of the page making the companies and the selected item data available to it. But now that we've created this scope object on the return value for our directive, our directive won't know about it. And so we actually, if we want our directive to render those companies, we have to pass those in. So why would we do that, you might ask? Well, the main reason is encapsulation and reusability. It makes our directives completely reusable because they aren't aware of their context at all. So anyone else who's using the directive has to pass in the data that directive needs explicitly for it to work. And it also prevents it from reaching outside of itself and messing things up. It's just basically about encapsulation. And this equals means that we want the data to be bound. So now we're asking for the user to pass in the data explicitly and then Angular's gonna take care of binding it. Binding the variable on the outside scope to this new separate variable, which is in our directive scope, right? So they're two different variables, but they're still gonna stay in sync. And we want this company info is really just, it's not this whole thing, it's just this piece. So if you look here, it's like this one thing is a company info directive. That's the idea. And so what does our company info directive need to render? Well, it just needs a company, right? And then we can render its name and its revenue. And we also want to know what the selected item is from the outside world so it can change what it's showing. And so we ask for both a company and a selected item. And then when we actually render it, so let's hide this, which is our normal template. This is how we render it. And this is kind of neat. This is the syntax we use for rendering our directives. And because Angular scans the document first and then generates everything it does, we get to use our own custom directive as if it were a native HTML element. So we just write company info and we pass in a company C. Well, what is C? We want to repeat over all of the companies in our collection. So for each company, we want to render a company info directive and we pass in the company and we also pass in the selected item. And we're still filtering by the query. And so I just added a border just to show they're different. And you can look in the DOM, C. Of course you can't see you don't have this nice big monitor right here. There it is, company info, right? And then there's the information. And so it's the same thing and everything still works just as we expect. It filters and it shows what we've selected. So that's how you kind of encapsulate these chunks and make them reusable. All right, so now let's bring in D3. Only thing we've changed here is we haven't changed anything. We've just brought in D3 and we've brought in our chart, our bubble chart. So the first step is we want to make a directive, right? Just like we just saw, we want to do the same thing but make it for our D3 chart. The difference here is we're gonna create an instance of our chart in the top of this directive. It's still element restricted. Now the only thing we're passing in is data and we'll see why in a minute. And we have this new thing that's link function. And so remember in Backbone we have the option of rendering our view. And the parent view sometimes would create, generate the HTML and then append it. Or the view itself, we could use the render function to do what we need. Well in D3 we need actually to do the rendering in JavaScript as opposed to in the template. And so the link function is where we do that. Essentially, if you need to use JavaScript to do your rendering, you can do it in the link function. And the link function takes in the scope and then the element and then the attributes you pass in. And so this is the normal API that we made for our bubble chart, right? This is the same bubble chart we used in Backbone. And it's the same API we've given it. It's just we're passing in the element from the link function and the data from the directive, which we haven't passed in yet, but we will. And the last piece is that we're watching data. And here, because we're not using the template, Angular doesn't know how to automatically keep our view and our date in sync with the data when the data changes. So we need to add a watch. And this is basically what Angular's doing behind the scenes when it scans the template. But here we have to do it mainly because we're writing our own custom directive. And so this next step is to prepare the data and we want to massage it in a way that gets it ready for our chart. And this is the same controller as before. We can just add a new method, just like we did, we added a backbone method to our backbone collection. So we create a chart data method, which we can use as a property in our template and it maps the same data to the format we expect. So let's look at it. We just render our directive like this, bubble chart passing in the data. Chart data will be executed because, again, it's in the same context and so it's on the right scope. So if we look at this, there we see our chart. Same chart as before and we're getting to reuse it. So the problem is it's not really staying in sync with the other user interactions that we've added. So that's what we want to do next. We want to first, we want to share the filtered companies. Now we could use the piping again, but as your application grows in complexity, it sometimes makes more sense to extract that out into its own property on your scope. So here we create a filtered property property, a filtered company's property on our scope and that watches the query. Again, this is essentially what Angular is doing behind the scenes at our templating layer, but we do it manually, right? We just watch the query variable when the user types and we update our filtered companies to filter down the list. And we're using the same filter, the filter directive that we used in the template. We can also use that in JavaScript. And so now we have this shared property and up here in our list, instead of saying see in company's filter query, we can just say see in filtered companies, right? And then in our chart data, we want to instead of looking, instead of mapping our scopes companies, we want to watch the filtered companies and then recalculate our chart data based on those filtered companies. So this is exactly the same function as before. It's just that we're updating it every time the filtered companies changes. So with watches, in essence, you begin to specify your dependency graph, right? As different parts of your GUI depend on other parts and they change, you need to make sure they all stay in sync in the way you do that as with watches. And so now when we filter, the chart keeps in sync. So we wanna see how Dunder Mithlin's doing compared to Stark Industries, not so good. Okay, the last part is we change the cost in the revenue, but these areas we've hard coded in revenue. We want it to change. And so to do that, instead of just watching the filtered companies, we want to watch both the filtered companies and the selected item. And instead of hard coding in revenue, we will just pass back whatever item is selected and this ARR is the array of dependencies that we're watching. So the second element, the first indexed element, is the selected item. And so now when we change cost, our chart updates. Right, so pretty cool. We can filter it and we can look, change revenue and costs, very simple to get this going and everything is staying in sync. So some thoughts about Angular, right? We enhanced our bubble chart in isolation. Our bubble chart doesn't know about Angular or any of the concepts filtering, right? It's its own reusable thing. The directive made it easy to incorporate and you have to remember to watch the different properties so that all your dependencies stay in sync with each other. And there's something in Angular called services which is, lets you inject objects that your controller or other objects need and you can even use your chart as a service or D3 itself instead of instantiating it within the directive. So some people do that. Okay, so now let's wrap up with Ember. Ember is the most opinionated of the frameworks and it tries to nudge you in the right direction more so. Because of this, it's definitely more important to understand how things work or else you're gonna run against roadblocks and ultimately what you'll find is you end up deleting the 10 lines of code you were doing to try to accomplish the thing you wanted to and it's just one line that does it. Ember has objects called components which are the equivalent of directives and views, essentially, they're essentially the same thing. They represent isolated portions of your GUI. The router is very important in Ember. It is kind of Ember's state machine. It's what's responsible for keeping everything, wiring everything up together instantiating everything using the container but as the user moves through your app to the different routes, the router is what keeps everything in sync. And so I just mentioned this because it's important to understand philosophically where they're coming from as you incorporate your D3 code with the rest of your Ember app. So let's take a look at Ember and I won't be able to go in detail to everything. I wanna get to the D3 code. So the first step is to just instantiate the app and we create our resources. We wanna represent a list of companies and then also a detailed view of a company. And so that's how we do this. Now, the route itself is what is responsible for getting the data from usually our server and providing it to our view. So we create a company's route and here we're returning the same data that we have been. In this model hook, I'm going a little fast just because I'm running a long time but all this code is gonna be available and you'll look at it, you can look at it. It's all the same code as I'm talking about here and so hopefully you'll be familiar with it. But essentially model hook is how we return the data and now our data is available in our template, right? To actually make a view, we use handlebar templates and the script tag you might have seen this in Backbone as well is a way to do this in line. Again, you can break these out into separate files but we create this company's ID and that's how Ember knows for the company's route which is the list of our objects, we wanna render a list. This is the view that has access to those models that we returned and then we just use handlebars and iterate over and there's a list of our companies. So pretty straightforward. Now we wanna add a detail view so that here we see the list but when we visit slash one, let's say, we can see a detail view of the company and so we do the same thing, we define what model is returned, we just point to the corresponding model in our company's collection and then we create a detail route the same way we created the company's route and so the ID tells Ember that this is what we wanna display when we're on a company route and it has access to the model that we returned and so these handlebars variables represent the variables from that company object. Now if we render this, we actually don't see anything and that's because we haven't told our parent view where to render the child view and so to do that, we use outlet and so this is the same as before except we've added this detail pane with an outlet and now when we visit slash one, we see the detail so here's the list, this is staying the same but as we navigate to the different models the detail is changing and we can use the forward and back button and that's how Ember router is keeping everything wired together. Okay so I'm gonna skip forward once we get the rest of it done so I make these links, that's all I do and these are helpers in Ember and that's obviously we don't want the user to type in the URL every time they change so this moves the router through the different states and so how do we bring D3 into this? Well this similar to the directive in Angular this is a component and the component is made in much the same way so that component is, the template is right here, components, company detail and the first step here is to make a bubble component. We do that by extending the Ember component and we instantiate our chart and then we want to similarly how we did it in the other frameworks create a function that actually renders and similar to the directive in Angular we pass in our data to our Ember component from the outside and then this is how we can specify tell our function to redraw itself when the data changes and then draw itself once when the element is first inserted so to pass in the data we do a similar thing where we add the chart data method on our controller and so this company's controller we didn't use it last time it existed before but we can redefine it here just like we redefined our backbone collection and so here we pass we create this method and so now we have the chart wired up and so and this is being synced to the data now the data is not changing in this case but what we want to do is let the user navigate through the routes using the bubble chart and so it basically involves passing in the dependencies just like we did in the directives and so how this looks at the end of it here's our finished app just want to show you how it ends so when you can look at the code later you can see well this is not working right now but essentially we go through the same process and here let me get rid of this and what we do is the user can click on the bubbles it navigates right the URL is changing and everything is staying in sync we can refresh the page and the bubble is selected and it's highlighted and so that way everything is kept in sync so more important than the details are the big picture that we want to create our D3 chart in this reusable way and keep it isolated from our app and as we build out our application using the framework we let the things in the framework influence the chart's API and there's ways to bring in and incorporate that API with all the frameworks and so that way you kind of create this reusable object and you build out your micro library of charts and their framework agnostic but charts are now kind of first class within your application so I'll stop my talk there, thanks a lot.