One of the more opaque concepts about AngularJS is the process that converts a chunk of HTML from a template into “Angularized” HTML which is then inserted into the DOM. During this conversions, custom directives are replaced with their corresponding HTML content, Angular directives like ng-repeat are processed, and any event handlers of interest are wired up. As it turns out, Angular’s $compile service is what’s responsible for making the magic happen. OK great, but why is this interesting or important? Because leveraging the $compile service directly lets you take dynamic content and process it to enable Angular directives and behaviors.
Since examples are always helpful, here’s an admittedly contrived one that we’ll walkthrough. Imagine that we’re building a WordPress slideshow plugin and we want to support custom themes for individual slides. So in our plugin, a user would be able to modify the HTML that displays a slide, we’d save it to the database, and then retrieve that template when we render the slides. For arguments sake, let’s assume the “default” template for the slideshow looks something like this:
As you can see, we’ve got a few directives and by default we’re displaying some description. Generally, we could set this up by creating a “slide” directive that looks something like:
Great, nothing to crazy but with this setup there’s no way to supply dynamic HTML from our database to use in the template. In order to allow a custom template you’d just need to modify the directive to look something like:
And then you’d be able to use it with:
The key difference is that in the modified directive the template is inserted into the directive’s element using “angular.element(el).html(scope[“slide”].template);” and then finally the $compile service is invoked to process the regular HTML to get Angular magic.
Anyway, as always questions or comments welcome!
A couple of days ago in my journey down the AngularJS rabbit hole I ran into an interesting issue. If you have a directive that’s dynamically adding an iframe tag how can you set an onLoad handler on the iframe with access to the directive’s $scope?
Interestingly, the top StackOverflow answer on Google recommends adding a function to the window object and then setting the onLoad attribute to that function. Although it works, this approach is decidedly not “the Angular way” and would definitely become unwieldy with more than one iframe on the page. I poked around a bit and turns out there’s a better way to do this. The “trick” is that it’s possible to access a directive’s $scope from inside its link function so you can set onLoad on the iframe element from there. This post provides an overview but it’s a bit light on details so here’s a concrete example.
Looking at code, a good starting point would be talking through the difference between “Duck” in the following sample:
Jumping back into code. An interesting first discussion would be “How could you implement a switch statement without using ‘if’ statements or a ‘switch’ block?”
Getting a bit fancier, another task would be to implement a “filter” method similar to the one found in lodash/underscore. “filter” accepts an array of elements and a callback and returns the elements which return “true” when passed to the callback. So as an example:
Jumping back into some code. A good first task would be to execute a set of asynchronous operations in series – Another interesting task would be to implement a tiny API using regular callbacks and then using a Promises library.
Anyway, just a couple of quick ideas. I’m still new to the recruiting and interviewing game so I’d love any feedback or comments!
We’ve been doing a bit of AngularJS work (more on that later) recently and true to its reputation there’s an “Angular way” to accomplish most things. Interestingly, one area where I couldn’t find a “one true way” was how to facilitate mixins between controllers or scopes.
Quickly taking a step back, a “mixin” is a form of horizontal reuse that allows two objects to share code without necessarily sharing a common ancestor in an inheritance chain. With concrete examples, you might have a Dashboard and Billing controller which need to share formatting logic but nothing else you’d want to use mixins vs. traditional inheritance. In traditional object oriented language mixins are typically referred to as Traits.
Anyway, back to AngularJS. Let’s say we have some simple logic that we want to share between two scopes:
It’s a contrived example but the “idea” is that you want to share the “selectAnswer” and “getAnswerClass” functions between $scopes of two unrelated controllers. After doing some research, it seems like the cleanest way to do this in Angular is to create a service that contains the functions, inject that into the controller, and then use angular.extend() to add them to the $scope as needed:
And that’s pretty much all there is to it. I’m pretty new to the Angular dance so I’d love any feedback!
So how do you go about making a puzzle? You can see the end result at HTML5 Canvas Puzzle and the code is online at https://github.com/Setfive/setfive.github.com/tree/master/canvas_puzzle.
As it turns out generating an arbitrary puzzle programatically is reasonably complicated. The best explanation I could find on how to accomplish this is at https://www.allegro.cc/forums/thread/586750/603411#target. Conceptually, the process looks straightforward enough and you could probably manually do it on a whiteboard. Unfortunately, the issue I ran into with this approach is that drawing bezier curves and splines programmatically on a Canvas is a bit involved. I also don’t have a background in vector graphics so I was getting stuck in the weeds drawing lines.
Discounting generating the puzzle entirely on the fly, an alternative approach would be to use a fixed set of available pieces and then “fill in” a grid depending on how large the image area is. Conceptually, the idea is to construct a closed grid of pieces where some number of the pieces can be repeated and then repeat those pieces as needed to cover the target image. The templated pieces I used are in /puzzle_pieces/.
Walking through the code, the steps to build a puzzle are fairly straightforward:
And that’s about it. One other “trick” is that you can use Window.requestAnimationFrame to avoid locking the UI when you’re creating the masked images since it’s a compute intensive task.
Anyway, as always questions and comments welcome.