This is the 4th post of a series about building WordPress themes with AngularJS and WP REST API (WP API).
In previous posts (1st, 2nd, 3rd) I’ve covered several topics in AngularJS with a very simple WordPress theme, include:
Module
We registered our application as a module
called app
to AngularJS. By adding a new attribute ng-app="app"
to <html>
in header.php
, we can run the WordPress site as an AngularJS app. If our app requires other modules to run, we can add them to an array in the second parameter:
Route
With ngRoute
when we change the path in our application, other than refreshing the whole page, only part of it (content in ng-view
) will get updated. That makes our app a Single Page Application (SPA).
Controller
In the controller functions we set the initial state of a $scope
object. For instance, we get a bunch of posts or a single post from WordPress (database) and attach them to the $scope
object. We use them in our view with syntax like {{post.title}}
. The other usage of controllers is to add behavior (functions) to the $scope
object.
ngSanitize and ngBindHtml
When binding raw HTML or special characters (like HTML entities) to the page content, we should pass them via ngBindHtml
directive, so ngSanitize
module will return the sanitized and properly escaped string on the page.
Custom Directive
We can create custom directives as template tags like get_search_form()
in WordPress. We built the searchForm
directive and added a function to make it search for posts when the search keyword changed. In the beginning of 2015 I would like to do a code cleanup for the series of tutorials and share a very important concept in AngularJS with you, that is Dependency Injection (DI).
Minification Errors in my AngularJS WordPress theme
To clean up the code I assign the app module to an app variable, other than chaining everything together, I can write the config, controllers and directives in separated blocks. After that I use CodeKit to minify the scripts.js (you can use a free service like this), and use the minified version in my demo theme. But it turns out the minified version of scripts.js
causes errors, and the app doesn’t work. To make my scripts.js
“minification safe”, there are 2 methods I can use.
Method one: inline array annotation
If we adopt this method, we’ll use a special syntax to write the constructor function of config and controllers. We pass an array whose elements consist of a list of strings followed by the function itself. And you must have noticed, the string elements in the array are exactly the same as the parameters of the function.
Method two: $inject property annotation
This method makes your code more organized and readable. We’ll assign the constructor function to an variable, then assign an array (consists of a list of strings like method one) to the $inject property of this variable.
What does the two methods have in common?
The two annotations are both provided by AngularJS, according to the document, method one is preferred. Though they do have one thing in common: the ordering of the values in the array must match the ordering of the parameters. That means, the names of parameters in the constructor function can be different from the string elements in the array, as long as the ordering is matched. For example:
Just update the scripts.js with one of the annotation above, and minify it again, you’ll eliminate all minification errors!
Dependency Injection does the magic
When I learned step by step with this WordCamp video: Eric Wolfe: Building a WordPress Theme Using AngularJS, it looks like I don’t have to set the data of parameters in the controller functions, I can use them right away, how amazing!
It’s when I read the ng-book later, I knew the magic is done by a design pattern called Dependency Injection. In the AngularJS document, it is described as:
Dependency Injection (DI) is a software design pattern that deals with how components get hold of their dependencies.
The Angular injector subsystem is in charge of creating components, resolving their dependencies, and providing them to other components as requested.
So when we create the constructor function for a component (like controller, config, or directive) in AngularJS, all parameters of the function are “dependencies” – the component depends on them.
Take our theme for example, since one of the purposes of a controller is to set up the initial state of the $scope
object, we need to set the $scope
object as its dependency.
Dependency annotations
The first annotation we learned from this series of tutorials, is called “implicit annotation”. Which is described in the AngularJS document as “the simplest way to get hold of the dependencies is to assume that the function parameter names are the names of the dependencies.”
That’s pretty straight forward, as long as we use the names of the objects / services as the parameter names, e.g. $scope
, $http
, $routeParams
, AngularJS will go get them for us. And of course we can reorder these parameters as we want, AngularJS only care if the names are right, the order doesn’t matter at all.
Oops! Minifiers change the names of the parameters
Even we don’t know how exactly the JavaScript minifiers/obfuscators work, but it’s obvious that they remove spaces and line breaks, and also rename the parameters and variables, to get the scripts clean (ugly) and shorter.
Now we realize the minification errors are fairly reasonable – the parameters are renamed by the JavaScript minifiers. That’s how they break our code.
Why those 2 “minfication safe” methods work
The method one “inline array annotation”, is the way AngularJS uses to keep track of the names of parameters. You can do the test by paste a sample array to an online Javascript minifier, like this:
You’ll see that if the element is a string, it won’t be renamed, the “$scope” is still “$scope”, “$http” is still “$http”, and so on.
So AngularJS can map the function parameters to the array elements, and figure out what exactly objects they should be. That’s also why the “ordering” becomes so important – it’s the key to make the mapping right.
As to the “$inject property annotation”, the syntax should be self-explanatory that it won’t be affect by JavaScript minifiers.
Download the updated theme
Now you can get the updated theme from my Github repo as a zip file. I hope you understand AngularJS better with this tutorial, or at least know how to eliminate minification errors in your scripts.
See you in next tutorial!
Leave a Reply