Skip to content

Commit

Permalink
Merge pull request Polymer#431 from arthurevans/databinding-updates
Browse files Browse the repository at this point in the history
Databinding updates
  • Loading branch information
ebidel committed Jun 5, 2014
2 parents d2e3d0b + 80d2105 commit d837da0
Show file tree
Hide file tree
Showing 8 changed files with 137 additions and 94 deletions.
12 changes: 12 additions & 0 deletions _includes/samples/databinding/auto-binding.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!-- <link rel="import" href="/elements/demo-tabs.html"> -->

<demo-tabs selected="0" bottom>
<demo-tab heading="index.html">
{% highlight html %}
{% include_external samples/databinding/auto-binding.html doc-sample %}
{% endhighlight %}
</demo-tab>
<div class="result">
{% include_external samples/databinding/auto-binding.html runnable-sample %}
</div>
</demo-tabs>
4 changes: 2 additions & 2 deletions _plugins/include_external.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ def initialize(tag_name, param_string, tokens)
@output = []

begin
startpattern = /^\s*(?:\/\/|<!--)\s*\[START\s+(\w*)\s*\]/
endpattern = /^\s*(?:\/\/|<!--)\s*\[END\s+(\w*)\s*\]/
startpattern = /^\s*(?:\/\/|<!--)\s*\[START\s+(\S*)\s*\]/
endpattern = /^\s*(?:\/\/|<!--)\s*\[END\s+(\S*)\s*\]/
f = File.new(@filename, "r")
text = f.read()
text.each_line do |line|
Expand Down
54 changes: 52 additions & 2 deletions docs/polymer/binding-types.md
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ How these bindings work depends on the element being bound:

- Custom elements are also free to interpret bindings in other ways. For example, a non-{{site.project_title}} element could use the underlying [Node.bind](node_bind.html) library to override the default handling of named bindings.

#### Binding to input values
### Binding to input values

Two-way bindings are supported as a special case on some user input elements. Specifically, the following attributes support two-way bindings:

Expand All @@ -239,7 +239,7 @@ Two-way bindings are supported as a special case on some user input elements. Sp
- `select` element: `selectedIndex` and `value` attributes.
- `textarea` element: `value` attribute.

#### Binding to {{site.project_title}} published properties
### Binding to {{site.project_title}} published properties

When you bind to a [published property](polymer.html#published-properties) on a {{site.project_title}} element, you get a two-way binding to the property.

Expand Down Expand Up @@ -281,6 +281,56 @@ binding system creates the property automatically.
{: .alert .alert-info }


#### Binding objects and arrays to published properties

Most of the examples show data binding with simple string values,
but {{site.project_title}} lets you bind references between elements
using published properties.

Let's modify the `name-tag` example to take an object instead of individual
properties.

<polymer-element name="name-tag" attributes="person">
<template>
Hello! My name is <span style="color:"{%raw%}{{person.nameColor}}{%endraw%}">
{%raw%}{{person.name}}{%endraw%}</span>
</template>
<script>
Polymer('name-tag', {
created: function() {
this.person = {
name: "Scott",
nameColor: "orange"
}
}
});
</script>
</polymer-element>

Now, imagine we make a new component called `<visitor-creds>` that uses `name-tag`:

<polymer-element name="visitor-creds">
<template>
<name-tag person="{%raw%}{{person}}{%endraw%}"></name-tag>
</template>
<script>
Polymer('visitor-creds', {
created: function() {
this.person = {
name: "Scott2",
nameColor: "red"
}
}
});
</script>
</polymer-element>

When an instance of `<visitor-creds>` is created, its `person` property (an object)
is also bound to `<name-tag>`'s `person` property. Now both components are using
the same `person` object.



### Conditional attributes

For boolean attributes, you can control whether or not the attribute appears using the special conditional attribute syntax:
Expand Down
50 changes: 20 additions & 30 deletions docs/polymer/databinding-advanced.md
Original file line number Diff line number Diff line change
Expand Up @@ -243,42 +243,32 @@ want to use data binding elsewhere, there are two options:

* Use the [Template Binding](/docs/polymer/template.html) library directly. The template binding library is
used internally by {{site.project_title}}, and can be used directly, with or without the rest of
{{site.project_title}}.
{{site.project_title}}. (Note that if you use template binding by itself, you cannot use {{site.project_title}}
expressions.)

### Using the `<polymer-body>` element
### Using the auto-binding template element

The `<polymer-body>` element is a {{site.project_title}} custom element that extends the standard
`<body>` element. You can use it when you want to use {{site.project_title}} features like data
binding in a document without having to create a custom element just for this purpose. For example,
to use data binding at the top level of a document:
The `auto-binding` element is a {{site.project_title}} custom element that extends the standard
`<template>` element. You can use it when you want to use {{site.project_title}} data
binding in a page without having to create a custom element just for this purpose. Auto-binding
templates support a subset of the features available when you create your own custom element:

{% raw %}
<body is="polymer-body" unresolved>
- Full-featured data binding, with {{site.project_title}} expressions.
- [Declarative event mapping](polymer.html#declarative-event-mapping).
- [Automatic node finding](/polymer/polymer.html#automatic-node-finding).

<!-- render data set -->
<template repeat="{{quotes}}">
<h3>{{quote}}</h3>
- <em>{{attribution}}</em>
</template>
For an auto-binding template, the data model is on the template itself. For example, to use data
binding at the top level of a page:

<script>
window.model = {
quotes: [{
attribution: "Plautus",
quote: "Let deeds match words."
}, {
attribution: "Groucho Marx",
quote: "Time flies like an arrow. Fruit flies like a banana."
}]
};
</script>
</body>
{% endraw %}
{% include samples/databinding/auto-binding.html %}

The auto-binding template inserts the instances it creates immediately after
itself in the DOM tree (_not_ in its shadow DOM). In this case, the quotes are
inserted as children of the `body` element.

A few things to note: since the `<polymer-body>` element doesn’t have its own model data, you need
to make the model data available to the template by adding a `model` property on `window`. The
`<polymer-body>` element looks for the `window.model` property and gives it special treatment.
After adding the instances, the auto-binding template fires the `template-bound`
event.

The `<polymer-body>` element is currently included automatically when you load the
The `auto-binding` element is currently included automatically when you load the
{{site.project_title}} library.

2 changes: 1 addition & 1 deletion docs/polymer/databinding.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ For {{site.project_title}} elements, **the model is always the element itself**.
this.owner = 'Rafael';
}
});
</script>
</script>
</polymer-element>
{% endraw %}

Expand Down
18 changes: 17 additions & 1 deletion docs/polymer/expressions.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ Expressions support the following subset of JavaScript:

| Feature | Example | Explanation
|---------|
|Identifiers & paths | `foo`, `foo.bar.baz` | These values are treated as relative to the current scope, extracted, and observed for changes. The expression is re-evaluated if one of the values in the expression changes.
|Identifiers & paths | `foo`, `match.set.game` | These values are treated as relative to the current scope, extracted, and observed for changes. The expression is re-evaluated if one of the values in the expression changes. Changing a property value does not result in the expression being re-evaluated. For example, changing the value of `foo.bar` doesn't cause the expression `foo` to be re-evaluated.
| Array access | `foo[bar]` | Where `foo` and `bar` are identifiers or paths. The expression is re-evaluated if `foo` or `bar` changes, or if the value at `foo[bar]` changes.
| Logical not operator | `!` |
| Unary operators | `+foo`, `-bar` | Converted to `Number`. Or converted to `Number`, then negated.
| Binary operators | `foo + bar`, `foo - bar`, `foo * bar` | Supported: `+`, `-`, `*`, `/`, `%`
Expand Down Expand Up @@ -130,6 +131,21 @@ to the filter:
{{site.project_title}} provides two predefined filters, `tokenList` and `styleObject`. You can also
create your own [custom filters](#custom-filters).

If your filter depends on the properties of one of the paths or identifiers in your expression,
note that the expression isn't re-evaluated when properties change. For example, if you have an
expression like:

{% raw %}{{ user | formatUserName}}{% endraw %}

The expression isn't re-evaluated when a property, such as `user.firstName` changes. If you need
the filter to be re-run when a property changes, you can include it explicitly in the expression,
like this:

{% raw %}{{ { firstName: user.firstName, lastName: user.lastName } | formatUserName }}{% endraw %}

Since `user.firstName` and `user.lastName` are included explicitly in this expression, both
properties are observed for changes.

### tokenList

The `tokenList` filter is useful for binding to the `class` attribute. It allows you
Expand Down
58 changes: 0 additions & 58 deletions docs/polymer/polymer.md
Original file line number Diff line number Diff line change
Expand Up @@ -598,64 +598,6 @@ In this example, the published property `name` has initial value of `null` and `

For more information see the [Data binding overview](databinding.html).

#### Binding objects and arrays to published properties

**Important:** Be careful when your properties are objects or arrays. Element
registration is evaluated once. This means only one instance of an object used
in property initialization is ever created. Because of the nature of
`prototype`, you may run into unexpected "shared state" across different
instances of the same element if you're setting an initial value for a property
which is an object or array. Do this type of initialization in the `created`
callback rather than directly on the `prototype`.
{: .alert .alert-error }

Generally, attributes are string values, but {{site.project_title}} makes it
possible to bind references between elements using published properties.

Let's modify the `name-tag` example to take an object instead of individual
properties.

<polymer-element name="name-tag" attributes="person">
<template>
Hello! My name is <span style="color:"{%raw%}{{person.nameColor}}{%endraw%}">
{%raw%}{{person.name}}{%endraw%}</span>
</template>
<script>
Polymer('name-tag', {
created: function() {
this.person = {
name: "Scott",
nameColor: "orange"
}
}
});
</script>
</polymer-element>

Now, imagine we make a new component called `<visitor-creds>` that uses `name-tag`:

<polymer-element name="visitor-creds">
<template>
<name-tag person="{%raw%}{{person}}{%endraw%}"></name-tag>
</template>
<script>
Polymer('visitor-creds', {
created: function() {
this.person = {
name: "Scott2",
nameColor: "red"
}
}
});
</script>
</polymer-element>

When an instance of `<visitor-creds>` is created, its `person` property (an object)
is also bound to `<name-tag>`'s `person` property. Now both components are using
the same `person` object.



### Declarative event mapping

{{site.project_title}} supports declarative binding of events to methods in the component.
Expand Down
33 changes: 33 additions & 0 deletions samples/databinding/auto-binding.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<!-- [START doc-sample] -->
<!DOCTYPE html>
<html>
<head>
<link rel="import" href="/components/polymer/polymer.html">
</head>
<body>
<!-- [START runnable-sample] -->
<!-- render data set -->
<template id="auto-bind-demo" is="auto-binding" repeat="{{quotes}}">
<div on-tap="{{quoteClicked}}">
<h3>{{quote}}</h3>
- <em>{{attribution}}</em>
</div>
</template>

<script>
var t = document.querySelector('#auto-bind-demo');
t.quoteClicked = function() {
alert('Quote clicked!');
};
t.quotes = [{
attribution: 'Plautus',
quote: 'Let deeds match words.'
}, {
attribution: 'Groucho Marx',
quote: 'Time flies like an arrow. Fruit flies like a banana.'
}];
</script>
<!-- [END runnable-sample] -->
</body>
</html>
<!-- [END doc-sample] -->

0 comments on commit d837da0

Please sign in to comment.