I offer a translation of the publication “AngularJs $ parse hacks” .In the depths of AngularJs, there is one small and wonderful feature:
$ parse . It is usually used inside a framework for interpolating values, for example, for two-way data binding:
<p>Hello, {{ user.name }}</p> // where user is an object in the scope
You can see this simple example
here .
To calculate the value of the
expression the user.name AngularJs will call $ parse, then put the result in the DOM.
')
$ parse converts
expressions , and not just lacks the properties of objects, for example:
<p>{{ 'Hello ' + user.name }}</p>
An example can be found
here .
You can use $ parse in your code by adding a dependency to the controller (or any other function). Calling $ parse involves two steps: compiling an
expression into a template function and then calling that function with context and local variables. Usually the context and local variables are the $ scope object:
function controller($scope, $parse) { $scope.user = { name: 'Joe' }; var template = $parse('Hello + user.name'); var msg = template($scope);
This two-step execution is also observed in other template libraries, such as
Handlebars .
In addition, $ parse forgives a lot, for example, if the $ scope.user object does not exist, the expression is normally converted, but returns undefined, which is displayed as an empty string, an example
here . This behavior of the $ parse function resulted in the following hacks:
Hack 1: secure access of nested properties
If we have an object with a property value that can be null, access to the nested properties of this property forces all sorts of checks:
var foo = { bar: { baz: { name: 'baz' } } }; var name; if (typeof foo === 'object' && typeof foo.bar === 'object' && typeof foo.bar.baz === 'object') { name = foo.bar.baz.name; }
Of course, you can use a third-party library like
l33teral and wrap objects for secure access:
var leet = require('l33teral'); var fooL = leet(foo); var name = fooL.tap('bar.baz.name');
But if you already use AngularJs, then just use $ parse:
var name = $parse('bar.baz.name')(foo);
Complete
example . If the property does not exist, the call will return undefined:
$parse('bar.baz2.name')(foo);
You can also assign the first step to a function in a variable, in order to avoid re-compiling the expression.
var getName = $parse('bar.baz.name'); ... getName(foo);
Hack 2: sending logic from the backend to the client
If you need to dynamically run something (calculate) on the client, you can send logic from the server as a string. In the line, in addition to methods, local variables can also be defined, for this $ parse is called with 2 arguments (context and local variables):
var ops = { add: function (a, b) { return a + b; }, mul: function (a, b) { return a * b; } }; var logic = 'mul(add(a, 1), b)'; var data = { a: 10, b: 4 }; var result = $parse(logic)(ops, data);
Complete
example .
The data argument may override properties in the context of the ops argument, but I recommend keeping methods separate from data for a more understandable implementation.
Hack 3: Spreadsheet in 20 minutes
To demonstrate the power of AngularJs in all its glory, I like to refer to
David Graunke's spreadsheet example . This is super awesome, an example that uses $ parse to dynamically transform expressions inside each cell. Expressions can refer to the values of other cells, which in turn can refer to other cells, etc. The basic logic of this example is that all cells are in scope, and the coumpute function is called every time the value of any cell changes.
function sheetController($scope, $parse) { $scope.columns = ['A', 'B', 'C', 'D']; $scope.rows = [1, 2, 3, 4]; $scope.cells = {};
Spreadsheet in action.