be-observant
TypeScript icon, indicating that this package has built-in type declarations

0.0.176 • Public • Published

be-observant [WIP]

Observe properties of peer elements or the host.

NPM version How big is this package in your project? Playwright Tests

[!Note] be-observant overlaps in functionality with be-sharing. The preference should be to use be-sharing when it is appropriate, especially when it can reduce busy work. be-sharing provides "wildcard" binding while sticking with attributes which are built in to the platform, attributes that serve other purposes in addition to binding (namely microdata). be-sharing works following an approach of "distribute data down" from the host or non-visible "brain" components, whereas be-observant works more on a "pull data in" to the adorned element.

[!Note] be-observant also provides similar functionality to be-bound. The difference is be-bound provides two-way binding between the adorned element and an upstream element, whereas be-observant is strictly one-way. Because it is one way, be-observant can apply some declarative adjustments to the value it is observing before applying to the adorned element.

[!Note] Although be-observant can declaratively adjust the value it is observing, it does not provide unfettered access to the JavaScript runtime though. It is a purely declarative element enhancement. For full access to the JavaScript runtime, use be-computed.

[!Note] An extra thin layer can be applied on top of be-observant, so that the original HTML that is streamed from the server can provide the initial values of the property that be-observant observes, and then once that initial handshake is established, lean exclusively on be-observant for all subsequent updates. This is handled by be-entrusting.

Example 1a (Hemingway Notation)

<my-custom-element>
    #shadow
    <input name=isVegetarian type=checkbox onclick="return false" be-observant>
</my-custom-element>

What this does: Binds my-custom-element's isVegetarian value to the input element's checked property.

So we are making the assumption here that if the user gives the input element name "isVegetatarian", that the choice of name will most likely match the identical property name coming from the host web component container.

If this assumption doesn't hold in some cases, then we can specify the name of the property we want to observe from the host:

Example 1b

<my-custom-element>
    #shadow
    <input type=checkbox onclick="return false" be-observant='of / is vegetarian.'>
</my-custom-element>

Slash indicates get value from host. If omitted, it is assumed:

Example 1c

<my-custom-element>
    #shadow
    <input type=checkbox onclick="return false" be-observant='of is vegetarian.'>
</my-custom-element>

The space between is and vegetarian can also be omitted, if case is specified: isVegetarian.

Special Symbols

In the example above, we mentioned using the / symbol to indicate to observe a property from the host. But be-observant can also observe peer elements within the ShadowRoot (or outside any shadow root be-observant adorns an element sitting outside any ShadowRoot).

What follows is a listing of other special symbols we can use to be able to observe other peer elements within the ShadowRoot realm. We stick to single character symbols in order to keep the statements small:

Symbol Meaning Notes
/propName "Hostish" Binds to a "propagator" EventTarget.
@propName Name attribute Listens for input events.
propName Itemprop attribute
#propName Id attribute Listens for input events.
%propName match based on part attribute Listens for input events.
-prop-name Marker indicates prop Binds to a "propagator" EventTarget.
~elementName match based on element name Listens for input events. [TODO]

"Hostish" means:

  1. First, do a "closest" for an element with attribute itemscope, where the tag name has a dash in it. Do that search recursively.
  2. If no match found, use getRootNode().host.

Example 1d Negation

<my-custom-element>
    #shadow
    <input type=checkbox onclick="return false" be-observant='of not is vegetarian.'>
</my-custom-element>

Example 1e Translation

<my-custom-element>
    #shadow
    <input type=readonly be-observant='of age - 20.'>
</my-custom-element>

Can also use addition (+), multiplication (*), division (/) [Untested].

Binding to peer elements

Example 2a

<input name=search type=search>

<div be-observant='of @search.'></div>

As the user types in the input field, the div's text content reflects the value that was typed.

Example 2b

<input id=searchString type=search>

<div be-observant='of # search string.'></div>

Example 2c Markers

<my-custom-element>
    #shadow
    <my-peer-element -some-bool-prop></my-peer-element>
    <input type=checkbox onclick="return false" be-observant='of -some-bool-prop'>
</my-custom-element>

This observes the my-peer-element's someBoolProp property for changes.

Example 2d Microdata

<link itemprop=isHappy>
...
<input type=checkbox be-observant='of | is happy.'>

Example 3a

<my-custom-element>
    #shadow
    
    <input name=someCheckbox type=checkbox>

    <my-peer-element be-observant='of @ some checkbox and assign to some bool prop'></my-peer-element>
</my-custom-element>

This watches the input element for input events and passes the checked property to someBoolProp of oMyPeerElement.

Example 3b

<input name=search type=search>

<div be-observant='of @search and assign to $0+beSearching:forText.'>
    supercalifragilisticexpialidocious
</div>

The plus symbol: $0+ is indicating to tap into a custom enhancement.

Example 4a (JavaScriptObjectNotation)

In some scenarios, it may be more effective to utilize the underlying binding model that the Hemingway statements above get transpiled to. This can be done as follows:

const oInput.beEnhanced.beObservant.observeRules = [
    {
        "remoteType": "/",
        "remoteProp": "isVegetarian",
        "localProp": "checked",
        "localSignal": {},
        "remoteSignal": {}
    }
]

Example 5 Mapping [TODO]

Example 6

<-->

Viewing Demos Locally

Any web server that can serve static files will do, but...

  1. Install git.
  2. Fork/clone this repo.
  3. Install node.js.
  4. Open command window to folder where you cloned this repo.
  5. npm install

  6. npm run serve

  7. Open http://localhost:3030/demo/ in a modern browser.

Running Tests

> npm run test

Using from ESM Module:

import 'be-observant/be-observant.js';

Using from CDN:

<script type=module crossorigin=anonymous>
    import 'https://esm.run/be-observant';
</script>

Package Sidebar

Install

npm i be-observant

Weekly Downloads

3

Version

0.0.176

License

MIT

Unpacked Size

24.4 kB

Total Files

8

Last publish

Collaborators

  • bahrus