There is a great little function hiding in AngularJs: $parse. Typically it is used internally to interpolate values, for example in two way binding:
1 | <p>Hello, {{ user.name }}</p> |
You can see this simple example in action at http://jsbin.com/pitoy/1.
Angularjs will call $parse
to evaluate the expression user.name
,
placing the result into the DOM.
$parse
evaluates expressions, not just property access, for example
you can achieve the same result with
1 | <p>{{ 'Hello ' + user.name }}</p> |
You can see this yourself at http://jsbin.com/pitoy/2.
You can use $parse
in your application code by injecting it into your
controller (or any other function). The parse operates in two steps: first
it compiles your expression into a template function. Then you call the
template function with a context and local variables. Your context and locals
are usually the $scope
object:
1 | function controller($scope, $parse) { |
The 2-step execution is similar to the way other templating libraries like Handlebars work.
$parse
is really forgiving, for example if the $scope.user
object does not
exist, the expression still evaluates fine, but returns an undefined which
is placed as empty string, see at
http://jsbin.com/pitoy/3.
This leads to my first $parse
hack.
Hack 1: safe deep property access using $parse
If we have an object with properties that might be null, grabbing a nested value requires lots of guard conditions
1 | var foo = { |
Of course you could use a helper library like l33teral and wrap objects for safer access
1 | var leet = require('l33teral'); |
But if you are already inside AngularJs application, just use $parse
1 | var name = $parse('bar.baz.name')(foo); |
See entire example at
http://jsbin.com/pitoy/4.
If a property does not exist, the call returns undefined
1 | $parse('bar.baz2.name')(foo); // returns undefined |
You can even store the first function to avoid recompiling the expression every time
1 | var getName = $parse('bar.baz.name'); |
Hack 2: send logic from backend to the client
If you need to dynamically compute something on the client, you can send the
logic from the server as a string. You can even split low level methods
and local variables when evaluating the parsed string by using $parse
with 2 arguments (context and locals)
1 | var ops = { |
See live code at http://jsbin.com/pitoy/5.
data
argument can override properties in the context argument ops
, but I suggest
keeping methods separate from data for cleaner implementation.
Hack 3: implement spreadsheet in 20 minutes
When demoing the AngularJs power, I like using David Graunke's
spreadsheet example. This is super impressive
example that uses $parse
to dynamically evaluate expressions inside each cell. The expressions
might refer to values of other cells, which can refer to other cells, etc. The relevant logic
is in placing all cells onto the scope and creating a compute
function that runs any time a user
changes a cell's value
1 | function sheetController($scope, $parse) { |
You can see the spreadsheet in action here.
Try entering any number in cell A1, then enter A1 + A1
in cell B1. As soon as you remove focus from
B1 it will show the computed value (which should be double the value of A1).