diff --git a/PRIMER.md b/PRIMER.md index b6564d82..38aa93d1 100644 --- a/PRIMER.md +++ b/PRIMER.md @@ -22,8 +22,8 @@ Bare-minum Custom Element sugaring | [Bespoke constructor support](#bespoke-constructor) | constructor: function() { … } | [Basic lifecycle callbacks](#basic-callbacks) | created, attached, detached, attributeChanged | [Native HTML element extension](#type-extension) | extends: ‘…’ -| [Publish API](#published-api) | published: { … } -| [Attribute deserialization to property](#attribute-deserialization) | published: { \: \ } +| [Configure properties](#property-config) | propertyConfig: { … } +| [Attribute deserialization to property](#attribute-deserialization) | propertyConfig: { \: \ } | [Module registry](#module-registry) | modularize, using | [Prototype Mixins](#prototype-mixins) | mixins: [ … ] @@ -46,15 +46,15 @@ Declarative data binding, events, and property nofication | [Local node marshalling](#node-marshalling) | this.$.\ | [Event listener setup](#event-listeners)| listeners: { ‘\.\’: ‘function’, ... } | [Annotated event listener setup](#annotated-listeners) | \ -| [Property change callbacks](#change-callbacks) | bind: { \: ‘function’ } +| [Property change callbacks](#change-callbacks) | propertyConfig: \: { observer: ‘function’ } | [Declarative property binding](#property-binding) | \ -| [Property change notification](#property-notification) | published: { \: { notify: true } } +| [Property change notification](#property-notification) | propertyConfig: { \: { notify: true } } | [Binding to structured data](#path-binding) | \ | [Path change notification](#set-path) | setPathValue(\, \) | [Declarative attribute binding](#attribute-binding) | \ -| [Reflecting properties to attributes](#attribute-reflection) | published: \: { reflect: true } } +| [Reflecting properties to attributes](#attribute-reflection) | propertyConfig: \: { reflect: true } } | [Computed properties](#computed-properties) | computed: { \: ‘function(\)’ } -| [Read-only properties](#read-only) | published: { \: { readOnly: true } } +| [Read-only properties](#read-only) | propertyConfig: { \: { readOnly: true } } | [Utility functions](#utility-functions) | toggleClass, toggleAttribute, fire, async, … | [Attribute-based layout](#layout-html) | layout.html (layout horizontal flex ...) @@ -211,12 +211,12 @@ MyElement = Polymer({ See the [section on configuring elements](#configuring-elements) for a more in-depth description of the practical uses of each callback. - -## Published API + +## Configuring properties -Placing an object-valued `published` property on your prototype allows you to define metadata regarding your Custom Element's API, which can then be accessed by an API for use by other Polymer features. +Placing an object-valued `propertyConfig` property on your prototype allows you to define metadata regarding your Custom Element's properties, which can then be accessed via an API for use by other Polymer features. -By itself, the `published` feature **doesn't do anything**. It only provides API for asking questions about these special properties (see featues below for details). +By itself, the `propertyConfig` feature **doesn't do anything**. It only provides API for asking questions about these special properties (see featues below for details). Example: @@ -225,7 +225,7 @@ Polymer({ is: 'x-custom', - published: { + propertyConfig: { user: String, isHappy: Boolean, count: { @@ -247,7 +247,7 @@ Remember that the fields assigned to `count`, such as `readOnly` and `notify` do ## Attribute deserialization -If an attribute matches a property listed in the `published` object, the attribute value will be assigned to a property of the same name on the element instance. Attribute values (always strings) will be automatically converted to the published type when assigned to the property. If no other `published` options are specified for a property, the type (specified using the type constructor, e.g. `Object`, `String`, etc.) can be set directly as the value of the property in the published object; otherwise it should be provided as the value to the `type` key in the `published` configuration object. +If an attribute matches a property listed in the `propertyConfig` object, the attribute value will be assigned to a property of the same name on the element instance. Attribute values (always strings) will be automatically converted to the propertyConfig type when assigned to the property. If no other `propertyConfig` options are specified for a property, the type (specified using the type constructor, e.g. `Object`, `String`, etc.) can be set directly as the value of the property in the propertyConfig object; otherwise it should be provided as the value to the `type` key in the `propertyConfig` configuration object. The type system includes support for Object values expressed as JSON, or Date objects expressed as any Date-parsable string representation. Boolean properties set based on the existence of the attribute: if the attribute exists at all, its value is true, regardless of its string-value (and the value is only false if the attribute does not exist). @@ -260,7 +260,7 @@ Example: is: 'x-custom', - published: { + propertyConfig: { user: String, manager: { type: Boolean, @@ -286,8 +286,6 @@ This user is a manager. --> ``` -**Warning:** Currently only lower-case published properties are supported. Camel-case property support will be added in this sprint. - ## Module registry @@ -358,7 +356,7 @@ using(['FunSupport', ...], function(funSupport, ...) { Polymer will "mixin" objects specified in a `mixin` array into the prototype. This can be useful for adding common code between multiple elements. -The current mixin feature in 0.8 is basic; it simply loops over properties in the provided object and adds property descriptors for those on the prototype (such that `set`/`get` accessors are copied in addition to properties and functions). Note that there is currently no support for publishing properties or hooking lifecycle callbacks directly via mixins. The general pattern is for the mixin to supply functions to be called by the target element as part of its usage contract (and should be documented as such). These limitations will likely be revisited in the future. +The current mixin feature in 0.8 is basic; it simply loops over properties in the provided object and adds property descriptors for those on the prototype (such that `set`/`get` accessors are copied in addition to properties and functions). Note that there is currently no support for configuring properties or hooking lifecycle callbacks directly via mixins. The general pattern is for the mixin to supply functions to be called by the target element as part of its usage contract (and should be documented as such). These limitations will likely be revisited in the future. The [module registry](#module-registry) should generally be used for registering mixins. Mixins registered with the Polymer module registry may be referred to by String name without needing to expliitly request the module via `using`. Otherwise, values in the `mixin` array should be an Object reference (generally retrieved via `using`). @@ -667,9 +665,9 @@ Example: ``` -## Property change callbacks +## Property change callbacks (observers) -Custom element properties may be observed for changes by specifying an object-valued `bind` property that maps element properties to chagne handler names. When the property changes, the change handler will be called with the new and old values. +Custom element properties may be observed for changes by specifying `observer` property in the `propertyConfig` for the property that gives the name of a funciton to call. When the property changes, the change handler will be called with the new and old values as arguments. Example: @@ -678,13 +676,14 @@ Polymer({ is: 'x-custom', - published: { - disabled: Boolean - }, - - bind: { - disabled: 'disabledChanged', - highlight: 'highlightChanged' + propertyConfig: { + disabled: { + type: Boolean, + observer: 'disabledChanged' + }, + highlight: { + observer: 'highlightChanged' + } }, disabledChanged: function(newValue, oldValue) { @@ -702,11 +701,9 @@ Polymer({ }); ``` -Note as in the example above, change handlers can be bound to properties that are not necessarily published. - Property change observation is achieved in Polymer by installing setters on the custom element prototype for properties with registered interest (as opposed to observation via Object.observe or dirty checking, for example). -Observing changes to object sub-properties is also supported via the `bind` object, by specifying a full (e.g. `user.manager.name`) or partial path (`user.*`). +Observing changes to multiple properties is supported via the `observers` object, by specifying a string-separated list of dependent properties that should result in a change function being called. These observers differ from single-property observers in that the change handler is called asynchronously. Example: @@ -715,11 +712,37 @@ Polymer({ is: 'x-custom', - published: { + propertyConfig: { + preload: Boolean, + src: String, + size: String + }, + + observers: { + 'preload src size': 'updateImage' + }, + + updateImage: function(preload, src, size) { + // ... do work using dependent values + } + +}); +``` + +Additionally, observing changes to object sub-properties is also supported via the same `observers` object, by specifying a full (e.g. `user.manager.name`) or partial path (`user.*`) and function name to call. In this case, the third argument will indicate the path that changed. Note that currently the second argument (old value) will not be valid. + +Example: + +```js +Polymer({ + + is: 'x-custom', + + propertyConfig: { user: Object }, - bind: { + observers: { 'user.manager.*': 'userManagerChanged' }, @@ -768,7 +791,7 @@ To bind to textContent, the binding annotation must currently span the entire co is: 'user-view', - published: { + propertyConfig: { first: String, last: String } @@ -796,7 +819,7 @@ To bind to properties, the binding annotation should be provided as the value to is: 'main-view', - published: { + propertyConfig: { user: Object } @@ -823,15 +846,15 @@ Note that currently binding to `style` is a special case which results in the va Polymer supports cooperative two-way binding between elements, allowing elements that "produce" data or changes to data to propagate those changes upwards to hosts when desired. -When a Polymer elements changes a property that was "published" as part of its public API with the `notify` flag set to true, it automatically fires a non-bubbling DOM event to indicate those changes to interested hosts. These events follow a naming convention of `-changed`, and contain a `value` property in the `event.detail` object indicating the new value. +When a Polymer elements changes a property that was configured in `propertyConfig` with the `notify` flag set to true, it automatically fires a non-bubbling DOM event to indicate those changes to interested hosts. These events follow a naming convention of `-changed`, and contain a `value` property in the `event.detail` object indicating the new value. As such, one could attach an `on--changed` listener to an element to be notified of changes to such properties, set the `event.detail.value` to a property on itself, and take necessary actions based on the new value. However, given this is a common pattern, bindings using "curly-braces" (e.g. `{{property}}`) will automatically perform this upwards binding automatically without the user needing to perform those tasks. This can be defeated by using "square-brace" syntax (e.g. `[[property]]`), which results in only one-way (downward) data-binding. To summarize, two-way data-binding is achieved when both the host and the child agree to participate, satisfying these three conditions: 1. The host must use curly-brace `{{property}}` syntax. Square-brace `[[property]]` syntax results in one-way downward binding, regardless of the notify state of the child's property. -2. The child property being bound to must be published with the `notify` flag set to true (or otherwise send a `-changed` custom event). If the property being bound is not published or if the `notify` flag is not set, only one-way (downward) binding will occur. -3. The child property being bound to must not published with the `readOnly` flag set to true. If the child property is `notify: true` and `readOnly:true`, and the host binding uses curly-brace syntax, the binding will effectively be one-way (upward). +2. The child property being bound to must be configured with the `notify` flag set to true (or otherwise send a `-changed` custom event). If the property being bound does not have the `notify` flag set, only one-way (downward) binding will occur. +3. The child property being bound to must not be configured with the `readOnly` flag set to true. If the child property is `notify: true` and `readOnly:true`, and the host binding uses curly-brace syntax, the binding will effectively be one-way (upward). Example 1: Two-way binding @@ -840,7 +863,7 @@ Example 1: Two-way binding -``` -Note, the `computed` property feature uses `debounce` under the hood to achieve a similar effect. ## Structured data and path notification diff --git a/README.md b/README.md index 9e4e4b3f..bbef9254 100644 --- a/README.md +++ b/README.md @@ -65,18 +65,18 @@ You can always fallback to using the low-level methods if you wish (iow, you cou By default, the default Polymer distribution include several features. Although `Polymer.Base` itself is tiny, if you examine `Polymer.Base` you will probably see several methods that have been plugged-in to that prototype by feature definitions. The next few sections will explain these features and why we include them in the default set. Keep in mind that it's entirely possible to construct custom feature sets, or even use a trivial, featureless form of `Polymer()`. -### Feature: _published_ +### Feature: _property-config_ -The first feature implements support for the `published` property. By placing a object-valued `published` property on your prototype, let's you define various aspects of your custom-elements public API. +The first feature implements support for the `propertyConfig` property. By placing a object-valued `propertyConfig` property on your prototype, let's you define various aspects of your custom-elements public API. -By itself, the `published` feature **doesn't do anything**. It only provides API for asking questions about these special properties (see [link to docs] for details). +By itself, the `propertyConfig` feature **doesn't do anything**. It only provides API for asking questions about these special properties (see [link to docs] for details). ```js Polymer({ is: 'x-custom', - published: { + propertyConfig: { user: String, isHappy: Boolean, count: { @@ -128,7 +128,7 @@ Many custom elements want to support configuration using HTML attributes. Custom Although it's relatively simple, having to write this code becomes annoying when working with multiple attributes or non-String types. It's also not very DRY. -Instead, Polymer's `attributes` feature handles this work for you (using the `published` feature data). If an attribute is set that matches a property listed in the `published` object, the value is captured into the matching property. Strings are automatically converted to the published type. +Instead, Polymer's `attributes` feature handles this work for you (using the `propertyConfig` feature data). If an attribute is set that matches a property listed in the `propertyConfig` object, the value is captured into the matching property. Strings are automatically converted to the specified type. The type system includes support for Object values expressed as JSON, or Date objects expressed as any Date-parsable string representation. Boolean properties are mapped to Boolean attributes, in other words, if the attribute exists at all, its value is true, regardless of its string-value (and the value is only false if the attribute does not exist). @@ -141,7 +141,7 @@ Here is the equivalent of the above code, taking advantage of the `attributes` f is: 'x-custom', - published: { + propertyConfig: { user: String }, diff --git a/docs/index.html b/docs/index.html index 0c84dfd2..e5c284c0 100644 --- a/docs/index.html +++ b/docs/index.html @@ -36,7 +36,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN diff --git a/explainer/samples.html b/explainer/samples.html index 9b44e4c0..f30400a3 100644 --- a/explainer/samples.html +++ b/explainer/samples.html @@ -33,7 +33,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN is: 'x-custom', - published: { + propertyConfig: { user: String }, diff --git a/polymer-micro.html b/polymer-micro.html index f38043c0..e547c99b 100644 --- a/polymer-micro.html +++ b/polymer-micro.html @@ -12,7 +12,7 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN - + @@ -75,7 +79,7 @@ diff --git a/test/unit/configure-elements.html b/test/unit/configure-elements.html index bfacea92..2166ee95 100644 --- a/test/unit/configure-elements.html +++ b/test/unit/configure-elements.html @@ -1,17 +1,14 @@