AngularJS Data Driven Directives Presentation Slides
Transcription
AngularJS Data Driven Directives Presentation Slides
AngularJS Data Driven Directives ! by Jeremy Zerr ! Blog: http://www.jeremyzerr.com LinkedIn: http://www.linkedin.com/in/jrzerr Twitter: http://www.twitter.com/jrzerr Github: https://github.com/jrzerr Plunker: http://plnkr.co/users/jrzerr Data Driven Directives Using D3.js to create data visualization Creating a Column Chart and Line Chart directive that uses D3 Making the chart interactive Creating chart Data Models and Options objects that correspond to each chart Transforming data from the server into chart Data Models compatible with the charts using a Mapper Challenges Create chart directives with a simple interface Organize the data in a structured way Transform domain data models into models compatible for displaying using the chart directives Avoid code duplication when creating multiple similar charts Keeping the D3 code separate from the directive to better adhere to Single Responsibility Principle Code and Demo Code is on Github at: AngularJS Data Driven Directives Live demo on my web site: Basketball Scorebook AngularJS Directive Interfaces The more complicated the directive… the more complicated the interface Different ways to create your directive interface Use directive scope to map all parameters individually Use a small number of directive scope items to pass larger complex data structures Directive scope with individual parameters An example: AngularJS NVD3 about 50 total… Directive scope with individual parameters To me this looks a lot like: function foo(var1, var2, var3, var4, var5, var6, …) { … } Whenever I see a function with too many arguments, code instincts kick in and tell me that something is not designed properly: the function is doing too much has too many dependencies typically solve by refactoring into subroutines or objects to encapsulate or replacing arguments with an object (or several) Using a data structure An example: ng-grid Using a data structure This is the method I prefer Notice the $scope.gridOptions.data argument, it is a string. Bit of magic… being a string is special, tells the ng-grid directive to $watch the data I feel better about having another parameter like “doWatchData: true” that is explicit Allows you to fine-tune your $watch and data-binding too, and even put the user in control of that through the directive options Also, since there are a lot of arguments, I prefer putting a little formality around that options structure and make it into its own Object Using a data structure Here is an example of my ColumnChartOptions object Default options already defined if you pass no options to the constructor. Options you want to override can be passed into the constructor Directive Inheritance? Creating a Column Chart and Line Chart, they are very similar. So maybe you want directive inheritance? I say not a good idea, a directive has a well-defined public API, you don’t want to pollute that with non-directive methods that you would need to allow overriding methods Consider a more flexible alternative: Within your directive link(), use a separate View object which you can then freely design with inheritance without worrying about the Directive API. Directive (View) Inheritance FTW! Let’s take a look at the ColumnChart directive at charts/columnchart/ColumnChart.js The chart creation heavy lifting is all in ColumnChartView, which inherits some of its functionality from ChartView. Chart Objects Each chart (Column Chart and Line Chart) have 4 types of objects: columnChart (directive <column-chart>) ColumnChartOptions (chart configuration options) ColumnChartView (does the D3 rendering) ColumnChartModel (data model displayed by ColumnChartView) Why Create a ColumnChartModel? Maintaining sanity when moving large complex data around is critical. A ColumnChartModel is a great way to enforce a common data format that needs to be met before rendering the chart. Then write Mappers that are responsible for transforming one domain Data Model into the desired Chart Data Model. What does that process look like? Fetch data from server using $http from either GameService or PlayerService, this is initiated from the Controller. Before returning the data to the Controller, the response is transformed by the Services into the domain Models: GameModels and PlayerGameModels. When controller data changes (seen by $watch), the domain Models are mapped into the appropriate Chart Data Model. The Chart Directive is $watching the Chart Data Model, when the data changes, the Chart View is (re-)rendered. Doing backend-less development with a $httpBackend mock Also a part of this github project is an example of doing backend-less development by using a $httpBackend mock Great for isolating frontend from backend for testing and also development to avoid needing a dev node server to provide a REST API. I have taken the code from this github project and broke it out into a Plunker that adds more detail and more examples specifically on this topic. Structuring a D3 Directive D3 Basics Uses SVG + HTML5 + CSS3 Has its own implementations of a lot of jQuery DOMrelated functions. (selectors, styling, attributes, etc.) It’s pretty low-level library, there’s no LineChart function. You build it up from scratch by binding data to SVG entities. You can also integrate HTML with it too, for chart controls like tooltips, legends, buttons, etc. D3 Chart Components Scales for X and Y Maps data (domain) to a scale (chart pixels) Axis for X and Y Displays a scale Bind data to an SVG entity like a line or a rect Uses the scales to map the data to a chart location/dimension and plot Add title, legend, tooltips, buttons, etc Add events like on clicking a bar, hovering over a data point, dragging a timeline, or transitions between different chart types or changing data sources D3 Directive The Directive object link function calls the render() function on the View object (ColumnChartView or LineChartView). Take a look at the base ChartView object to find the render() function. Calls several render functions for different visual components. SVG, XAxis, YAxis, Title, Data Has functions for creating each of the components: scales, axes, SVG, title, data. These are overriden if necessary in the ColumnChartView or LineChartView objects. D3 Directive - Closer look at ColumnChartView Let’s take a closer look at ColumnChartView Pieces being overriden X and Y scales (not too much different than Line) Data Compare data portions Comparing renderData() ColumnChartView LineChartView Want to learn more? Look how nvd3 builds their D3 charts: nvd3 Chart.js is another alternative to D3: Chart.js Both have Angular adapters: Angular nvd3 and Angular Chart.js The Angular nvd3 library is used way more than Angular Chart.js My Demo code is on my blog: AngularJS DDD Demo Page Slides are on my blog: AngularJS DDD Presentation page See some code from this presentation, and more, at My Plunker Page Thanks! ! by Jeremy Zerr ! Blog: http://www.jeremyzerr.com LinkedIn: http://www.linkedin.com/in/jrzerr Twitter: http://www.twitter.com/jrzerr Github: https://github.com/jrzerr Plunker: http://plnkr.co/users/jrzerr
Similar documents
AngularJS 1.x Component-based Design
X-Files Villains App - Part 2 Refactor to directives One controller, three directives, one for each section of the app Data is all stored on $scope in controller, and passed via directive scope in...
More information