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 stateful interactivity to your AMP pages via data binding and JS-like expressions.

A simple example:

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

<button on="tap:AMP.setState({message: 'Hello World'})">

Tapping the button causes the <p> element's text to change to "Hello World".

Details

State

Each AMP document that uses amp-bind has document-scope mutable JSON data, or state.

The state can be initialized with the amp-state component:

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

Expressions can reference state variables via dot syntax. In this example, myState.foo will evaluate to "bar".

AMP.setState()

State can be mutated by the new AMP.setState() action.

  • AMP.setState() performs a shallow merge of its arguments with the document state.
  • AMP.setState() can override data initialized by amp-state.

Binding

A binding is a special attribute of the form [property] that links an element's property to an expression.

When the state changes, expressions are re-evaluated and the bound elements' properties are updated with the new expression results.

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:)

Element-specific attributes

Most attributes accepted by the AMP Validator for AMP and non-AMP elements, are bindable.

There are also special bindable attributes without non-bindable counterparts:

Component Attribute Details Example
amp-carousel[type=slides] [slide] The currently displayed slide index. Linked carousels
amp-selector [selected] The option attribute values of the currently selected children elements. Linked carousels

Expressions

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

  • Expressions may only access the document state
  • Expressions do not have access to globals like window or document
  • Only whitelisted functions are allowed
  • Custom functions, classes and control flow statements (e.g. for) are disallowed
  • Undefined variables and 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 grammar and implementation can be found in bind-expr-impl.jison and bind-expression.js.