Polymer mixin (behavior) for a web component to take a property value from the closest ancestor that has it
**[ This description is mirrored from README.md at [github.com/AqoviaElements/properties-from-ancestor-behavior](https://github.com//AqoviaElements/properties-from-ancestor-behavior/blob/v2.0.3/README.md) on 2019-05-10 ]**
![Published bower package version](https://badge.fury.io/bo/properties-from-ancestor-behavior.svg)
[![Build status](https://travis-ci.org/AqoviaElements/properties-from-ancestor-behavior.svg?branch=master)](https://travis-ci.org/AqoviaElements/properties-from-ancestor-behavior)
[![Published on webcomponents.org](https://img.shields.io/badge/webcomponents.org-published-blue.svg)](https://www.webcomponents.org/element/AqoviaElements/properties-from-ancestor-behavior)
_[Demo and API docs](https://www.webcomponents.org/element/AqoviaElements/properties-from-ancestor-behavior)_
## PropertiesFromAncestorBehavior
A Polymer Behavior for a web component to take a property value from the closest ancestor that has it. Supports change events.
## Where it might be a good idea?
It can be useful for ubiquitous properties (think [language of the UI](#html-lang), currency, [`disabled` state to every input of a form](#how-to-native-like-support-for-fieldset-disabled), etc.) which would otherwise pollute attributes of every component with same boilerplate expression, or force usage of a global variable (usually without binding to changes).
An extra feature of [being able to observe attributes](#ancestorObservedItem) helps with achieving easy-to-use web components, reusable in other app frameworks or pure HTML.
### Usage:
Technically, it's a behavior factory function. To have a behavior instance created, you call the `PropertiesFromAncestorBehavior()`.
```JavaScript
class MyComponent extends Polymer.mixinBehaviors([
PropertiesFromAncestorBehavior({
// Just declaring a property here is enough to make it work.
myProp1: {
// Optionally, you can provide a default. If no ancestor is found, `defaultValue` will be used:
defaultValue: 123, // (don't use the polymer's 'value:' for this though, because it may cause double initialization - once with such value, once with the value from ancestor (if they're different). That's because we can only reach the ancestor on 'attached', which happens after defaults get applied.
// See "API Reference - Per-Property settings" for all available options
// If you don't care about polylint, you can avoid repetition and just put here all other property settings. They get passed to declaration of this property on the element:
notify: true,
observer: '_myProp1Changed',
},
}) ], Polymer.Element)
{
static get is() { return "my-component"; }
static get properties() {
return {
// But if you want to keep polylint happy, you need to list the property here too:
myProp1: {
// Custom settings still work:
notify: true,
observer: '_myProp1Changed',
// But you don't want to use 'value:' here but rather 'defaultValue:' above. See comment there for 'why'.
}
};
}
}
```
the above declaration will make the properties available in ``s template:
```HTML
myProp1 value is {{myProp1}}
myProp2 value is {{myProp2}}
```
while their values will come from the closest ancestor that has the corresponding dash-case attribute.
```HTML
```
# API Reference - Per-Property settings #
These parameters can be specified for each property:
- **defaultValue** (_Optional_)
If no ancestor is found, `defaultValue` will be used.
- **ancestorMatches** (_Optional_)
of type HTML Selector
- Instead of looking for ancestor with the dash-case attribute, you can provide a selector. This especially is needed for boolean attributes that start with 'false', because it's represented as no attribute at all.
Example:
`ancestorMatches: '.ancestor-markup-class'` - will listen to the closest ancestor with `class="ancestor-markup-class"`
- **ancestorObservedItem** (_Optional_)
of enum type
`PropertiesFromAncestorBehavior.ObservedItem.PROPERTY_CHANGED_EVENT` (default)
`PropertiesFromAncestorBehavior.ObservedItem.ATTRIBUTE`
If the ancestor doesn't emit `*-changed` events, you can use `ATTRIBUTE` to tell the behavior that it should use a MutationObserver to listen to the attribute.
Take note that in this case the handlers will not fire in the same thread as the change, so if you need to schedule some work after the handlers, you will need to use `setTimeout(..., 0)`.
- **ancestorPropertyAlias** (_Optional_)
If the name of the property is different on the ancestor, specify it here (specify 'camelCase' name, but this will also change the expected dash-case attribute and '*-changed' event names).
# HOW-TO: Automatically reflect container's `lang` attribute in your multi-language component
The HTML lang attribute is a standard way to declare the content language. It's useful for applying `[lang=...]` CSS rules and is recommended for future applications.
It's then a perfect candidate to specify the language in one place and have your components automatically display the right contents:
```HTML
...
...
```
to achieve this effect with the Polymer's `AppLocalizeBehavior`, all you need to do is add our behavior next to it, with the following declaration:
```JavaScript
...
class ... extends ...
Polymer.AppLocalizeBehavior,
PropertiesFromAncestorBehavior({
language: {
// This is needed because `AppLocalizeBehavior` requires `language` for the name - see also https://github.com/PolymerElements/app-localize-behavior/issues/98
ancestorPropertyAlias: 'lang',
// Observing the attribute will allow changing the language and seeing immediate effect:
ancestorObservedItem: PropertiesFromAncestorBehavior.ObservedItem.ATTRIBUTE,
},
}),
...
```
# HOW-TO: Native-like support for `