Skip to content

Commit

Permalink
Update amp-bind docs (#7216)
Browse files Browse the repository at this point in the history
* update bind docs

* barb's comments
  • Loading branch information
William Chou authored Jan 27, 2017
1 parent 38afb0d commit f33b581
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 31 deletions.
68 changes: 41 additions & 27 deletions extensions/amp-bind/amp-bind.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ limitations under the License.
<table>
<tr>
<td class="col-fourty"><strong>Description</strong></td>
<td><code>amp-bind</code> allows elements to mutate in response to user actions or data changes via data binding and simple JS-like expressions.</td>
<td><code>amp-bind</code> allows adding custom interactivity with data binding and expressions.</td>
</tr>
<tr>
<td class="col-fourty"><strong>Availability</strong></td>
Expand All @@ -37,66 +37,80 @@ limitations under the License.
</tr>
<tr>
<td class="col-fourty"><strong>Examples</strong></td>
<td>TBD</td>
<td><a href="https://ampbyexample.com/components/amp-bind/">Annotated code example for amp-bind</a></td>
</tr>
</table>

## Overview

Once installed, `amp-bind` scans the DOM for bindings -- an element may have attributes, CSS classes or textContent bound to a JS-like expression (see [Expressions](#expressions) below).
`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.

The **scope** is mutable implicit document state that binding expressions may reference. The scope may be initialized with a new AMP component `<amp-state>`. Changes to the scope happen through user actions, e.g. clicking a `<button>` or switching slides on an `<amp-carousel>`.

A **digest** is an evaluation of all binding expressions. Since scope is mutable and expressions can reference the scope, the evaluated result of expressions may change over time. Bound elements are updated as a result of a digest.
A data binding is a special attribute that links an element to a custom [expression](#expressions). 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:

```html
<amp-state id=”foo”>
<script type=”application/json”>{ message: “Hello World” }</script>
</amp-state>
<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 &lt;p&gt;'s binding expression `message` to be re-evaluated.
3. The &lt;p&gt;'s text changes to show "Hello World".

<p [text]=”foo.message”>Placeholder text</p>
### Initializing state

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

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

1. `amp-bind` scans the DOM and finds the `<p>` element’s `[text]` binding.
2. During the next digest, `amp-bind` reevaluates the expression `foo.message`.
3. On the next frame, `amp-bind` updates the `<p>` element's textContent from "Placeholder text" to "Hello World".
Binding expressions can reference the data in this `<amp-state>` component via dot syntax.
In this example, `myState.foo` will evaluate to `"bar"`.

## Binding
## Data binding

`amp-bind` supports binding to three types of data on an element:
`amp-bind` supports data bindings on three types of element state:

| Type | Syntax | Details |
| --- | --- | --- |
| Attribute | `[<attr>]` | Only whitelisted attributes are supported.<br>Boolean expression results toggle boolean attributes.
| CSS Classes | `[class]` | Expression result must be a space-delimited string.
| Node.textContent | `[text]` | For applicable elements.

**Caveats:**
| [Node.textContent](https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent) | `[text]` | Supported on most text elements.
| [CSS Classes](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/class) | `[class]` | Expression result must be a space-delimited string.
| Element-specific attribute | `[<attr>]` | Only whitelisted attributes are supported.<br>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, generally all attributes are bindable.
For non-AMP elements, most attributes accepted by the [AMP Validator](https://validator.ampproject.org/) are bindable.

For AMP components, only a subset of attributes are bindable:
For AMP components, only select attributes are bindable:

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

Note that the set of bindable attributes will grow over time as development progresses.
See [BindValidator](./0.1/bind-validator.js) for the canonical set of bindable
elements and attributes.

## Expressions

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

- Expressions only have access to the **scope**, not globals like `window` or `document`
- 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
Expand Down
28 changes: 24 additions & 4 deletions spec/amp-actions-and-events.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,11 @@ AMP has a concept of a default action that elements can implement. So when omitt
**arg=value**
__optional__
Some actions, if documented, may accept arguments. The arguments are defined between parentheses in `key=value` notation. The accepted values are:
- simple unquoted strings: `simple-value`;
- quoted strings: `"string value"` or `'string value'`;
- boolean values: `true` or `false`;
- numbers: `11` or `1.1`.
- simple unquoted strings: `simple-value`
- quoted strings: `"string value"` or `'string value'`
- boolean values: `true` or `false`
- numbers: `11` or `1.1`
- dot-syntax reference to event data: `event.someDataVariableName`

## Handling Multiple Events
You can listen to multiple events on an element by separating the two events with a semicolon `;`.
Expand All @@ -76,21 +77,31 @@ For example, the following is possible in AMP.
<th width="30%">Tag</th>
<th>Event</th>
<th>Description</th>
<th>Data</th>
</tr>
<tr>
<td width="30%">amp-carousel</td>
<td>goToSlide</td>
<td>Fired when the user changes the carousel's current slide.</td>
<td><code>index</code> : slide number</td>
</tr>
<tr>
<td width="30%">form</td>
<td>submit</td>
<td>Fired when the form is submitted</td>
<td></td>
</tr>
<tr>
<td width="30%">form</td>
<td>submit-success</td>
<td>Fired when the form submission response is success.</td>
<td><code>response</code> : JSON response</td>
</tr>
<tr>
<td width="30%">form</td>
<td>submit-error</td>
<td>Fired when the form submission response is an error.</td>
<td><code>response</code> : JSON response</td>
</tr>
</table>

Expand Down Expand Up @@ -142,6 +153,11 @@ For example, the following is possible in AMP.
<td>update (default)</td>
<td>Updates the DOM items to show updated content.</td>
</tr>
<tr>
<td width="30%">amp-state</td>
<td>(default)</td>
<td>Updates the amp-state's data with the data contained in the event. Requires <a href="../extensions/amp-bind/amp-bind.md">amp-bind</a>.</td>
</tr>
<tr>
<td width="30%">amp-user-notification</td>
<td>dismiss (default)</td>
Expand Down Expand Up @@ -169,4 +185,8 @@ actions that apply to the whole document.
<td>goBack</td>
<td>Navigates back in history.</td>
</tr>
<tr>
<td>setState</td>
<td>Updates local bindable state. Requires <a href="../extensions/amp-bind/amp-bind.md">amp-bind</a>.</td>
</tr>
</table>

0 comments on commit f33b581

Please sign in to comment.