This extension is under active development, and the version number of the specification section should provide guidance to its evolution.

Description amp-bind allows adding custom interactivity with data binding and expressions.
Availability In development
Required Script
<script async custom-element="amp-bind" src="https://cdn.ampproject.org/v0/amp-bind-0.1.js"></script>
Examples Annotated code example for amp-bind

Overview

amp-bind allows you to add custom interactivity to your pages beyond using AMP's pre-built components. It works by mutating elements in response to user actions via data binding and JS-like expressions.

A data binding is a special attribute that links an element to a custom expression. Expressions may reference an implicit mutable JSON state. When that state is changed, expressions are re-evaluated and elements with bindings are updated with the new results.

A simple example:

<p [text]="message">Hello amp-bind</p>

<button on="tap:AMP.setState(message='Hello World')">
  1. When the button is tapped, the implicit state is updated with {message: 'Hello World'}.
  2. The state update causes the <p>'s binding expression message to be re-evaluated.
  3. The <p>'s text changes to show "Hello World".

Initializing state

The implicit state can be initialized at page load with custom JSON. For example:

<amp-state id="myState">
  <script type="application/json">
    {"foo": "bar"}
  </script>
</amp-state>

Binding expressions can reference the data in this <amp-state> component via dot syntax. In this example, myState.foo will evaluate to "bar".

Data binding

amp-bind supports data bindings on three types of element state:

Type Syntax Details
Node.textContent [text] Supported on most text elements.
CSS Classes [class] Expression result must be a space-delimited string.
Element-specific attribute [<attr>] Only whitelisted attributes are supported.
Boolean expression results toggle boolean attributes.
  • For security reasons, binding to innerHTML is disallowed
  • All attribute bindings are sanitized for unsafe URL protocols (e.g. javascript:)

Bindable attributes

For non-AMP elements, most attributes accepted by the AMP Validator are bindable.

For AMP components, the height and width attributes are bindable along with the following specific attributes:

Component Attributes
amp-carousel slide
amp-img src, srcset, alt
amp-selector selected
amp-video src, srcset, alt, controls, loop, poster

See BindValidator for the canonical set of bindable elements and attributes.

Expressions

amp-bind expressions are JS-like with some important differences:

  • Expressions may only access the implicit JSON state
  • Expressions do not have access to globals like window or document
  • Only whitelisted functions are allowed
  • Custom functions and control flow statements (e.g. for, if) are disallowed
  • Undefined variables, array-index-out-of-bounds return null instead of throwing errors

BNF-like grammar

expr:
    operation
  | invocation
  | member_access
  | '(' expr ')'
  | variable
  | literal

operation:
    '!' expr
  | '-' expr
  | '+' expr
  | expr '+' expr
  | expr '-' expr
  | expr '*' expr
  | expr '/' expr
  | expr '%' expr
  | expr '&&' expr
  | expr '||' expr
  | expr '<=' expr
  | expr '<' expr
  | expr '>=' expr
  | expr '>' expr
  | expr '!=' expr
  | expr '==' expr
  | expr '?' expr ':' expr

invocation:
    expr '.' NAME args

args:
    '(' ')'
  | '(' array ')'
  ;

member_access:
    expr member
  ;

member:
    '.' NAME
  | '[' expr ']'

variable:
    NAME
  ;

literal:
    STRING
  | NUMBER
  | TRUE
  | FALSE
  | NULL
  | object_literal
  | array_literal

array_literal:
    '[' ']'
  | '[' array ']'

array:
    expr
  | array ',' expr

object_literal:
    '{' '}'
  | '{' object '}'

object:
    key_value
  | object ',' key_value

key_value:
  expr ':' expr

Whitelisted functions

Array.concat
Array.indexOf
Array.join
Array.lastIndexOf
Array.slice
String.charAt
String.charCodeAt
String.concat
String.indexOf
String.lastIndexOf
String.slice
String.split
String.substr
String.substring
String.toLowerCase
String.toUpperCase

The full expression implementation can be found in bind-expr-impl.jison.