Declaring Data-Bindings

WebRxs declarative binding system provides a concise and powerful way to link data to the UI. It’s generally easy and obvious to bind to simple data properties or to use a single binding. For more complex bindings, it helps to better understand the behavior and syntax of WebRxs binding system.

The data-bind attribute

The data-bind attribute contains a collection of comma-separated options for how WebRx should bind view-model properties to an HTML element and optionally its children.

Binding consists of two items, the binding name, and expression, separated by a colon. Here is an example of a single, simple binding:

Todays message is: <span data-bind="text: myMessage"></span>

An element can include multiple bindings (related or unrelated), with each binding separated by a comma. Here are some examples:

Cellphone: <input data-bind="value: cellphoneNumber, enabled: hasCellphone" />

The binding name should generally match a registered binding handler (either built-in or custom) or be a parameter for another binding. If the name matches neither of those, WebRx will throw an error.

Binding Expressions

Binding expressions are JavaScript-like code snippets. For example, these are valid expressions in WebRx:

  • 1+2
  • a+b
  • user.name
  • items[index]
  • foo.@bar

Binding Expressions vs. JavaScript Expressions

WebRx expressions are like JavaScript expressions with the following differences:

  • Context: JavaScript expressions are evaluated against the global window. In WebRx, expressions are evaluated against the binding context object.
  • Forgiving: In JavaScript, trying to evaluate undefined properties generates ReferenceError or TypeError. In WebRx, expression evaluation is forgiving to undefined and null.
  • No Control Flow Statements: You cannot use the following in an expression: conditionals, loops, or exceptions.
  • No Function Declarations: You cannot declare functions in an expression.
  • No RegExp Creation With Literal Notation: You cannot create regular expressions in an expression.
  • No Comma And Void Operators: You cannot use, or void in an expression.
  • Filters: You can use filters within expressions to format data before displaying it.

Context

WebRx does not use JavaScripts eval() to evaluate expressions. Instead, WebRxs ExpressionCompiler processes these expressions.

Expressions do not have access to global variables like window, document or location. This restriction is intentional. It prevents accidental access to the global state – a common source of subtle bugs.

Forgiving

Expression evaluation is forgiving to undefined and null. In JavaScript, evaluating a.b.c throws an exception if a is not an object. While this makes sense for a general purpose language, the expression evaluations are primarily used for data binding, which often looks like this:

a.b.c

It makes more sense to show nothing than to throw an exception if “an” is undefined (perhaps we are waiting for the server response, and it will become defined soon). If expression evaluation wasn’t forgiving we’d have to write bindings that clutter the code, for example:

a||{}).b||{}).c

No Control Flow Statements

Apart from the ternary operator (a ? b : c), you cannot write a control flow statement in an expression. The reason behind this is core to the philosophy that application logic should be in view-models, not the views.

No function declarations or RegExp creation with literal notation

You can’t declare functions or create regular expressions from within expressions. This is to avoid complex model transformation logic inside templates. Such logic is better placed in a view-model or in a dedicated filter where it can be tested properly.

Expression Filters

Expression-filters format the result of an expression for display to the user. They can be used in every template and can be registered at module-level.

Using filters in templates

Filters can be applied to expressions in templates using the following syntax:

expression | filter

E.g. the markup 12 | currency formats the number 12 as a currency using the currency filter. The resulting value is $12.00.

Filters can be applied to the result of another filter. This is called “chaining” and uses the following syntax:

expression | filter1 | filter2 | ...

Filters may have arguments. The syntax for this is

expression | filter:argument1:argument2:...

E.g. the markup 1234 | number:2 formats the number 1234 with 2 decimal points using the number filter. The resulting value is 1,234.00.

Next: The Binding-Context