EPA-WG / custom-element

Declarative Custom Element
Apache License 2.0
18 stars 1 forks source link

slice to select multiple nodes in datadom #42

Open sashafirsov opened 4 months ago

sashafirsov commented 4 months ago

slice attribute defines the name of /datadom/slice/* node in element to be filled during initialization and when targetted event happen (the value is changed, clicked, etc. ).

In case of targetting of multiple slices or node(s) in another layer( like attribute ), XPath would identify those:

<custom-element>
    <attribute name="emotion" select="😃"/>
    <input slice="/datadom/attributes/emotion">

In given example the input filed should be initialized from and propagate the value into value attribute on the change event.

sashafirsov commented 4 months ago

Scenario: propagate multiple values on single event

On http-request demo we need to propagate the selected by click pokemon name and url into matching DCE attributes.


<custom-element>
    <template>
        <attribute name="name" />
        <attribute url="url" />
        <http-request url="https://pokeapi.co/api/v2/pokemon?limit=6&amp;offset=0" slice="page" method="GET" header-accept="application/json"></http-request>
        <variable name="slides-url">https://unpkg.com/pokeapi-sprites@2.0.2/sprites/pokemon/other/dream-world</variable>
        <for-each select="//slice/page/data/results/*">
            <variable name="pokeid" select="substring-before( substring-after( @url, 'https://pokeapi.co/api/v2/pokemon/'),'/')"></variable>
            <button
                slice="name"
                slice-event="click"
                value="{@name}"
                    > <img src="{$slides-url}/{$pokeid}.svg" alt="{@name}" /> {@name} </button>
        </for-each>
        Selected pokemon name: {/dataset/slice/name}
    </template>
</custom-element>

The single attribute propagation is straight forward.

<button slice-event="click" slice="//attributes/name" slice-value="{@name}" />
<button slice-event="click" slice="//attributes/url" slice-value="{$slides-url}/{$pokeid}.svg" />

How to propagate both? What if there is a need to have separate values for diffetent events?

Need to define the syntax for triplets: event(s) | XPath | value

The JSON kind of fits the bill. The keys would be unconventional: event listing (CSV?), XPath as a key.

{   "click tap" : 
    {   "//attributes/name": "{@name}"
    ,   "//attributes/url": "{$slides-url}/{$pokeid}.svg"  
    }
,   "hover": 
    {   "title": "{@name}" 
    }
}

Declarative convention is more verbose(?)

<button>
     <slice slice-event="click tap" slice="//attributes/name" value="{@name}" >
     <slice slice-event="click tab" slice="//attributes/url" value="{$slides-url}/{$pokeid}.svg" >
     <slice slice-event="hover"     slice="//attributes/title" value="{@name}" >
     ... img
</button

The declarative syntax unlike JSON would have the perks of validation, IDE suggestions, etc. in same fashion as other DCE parts. More consistent and functional.

sashafirsov commented 4 months ago

Should/How to handle initial value when multiple element use same slice?

<button slice-event="click" slice="xxx" value="AAA" />
<button slice-event="click" slice="xxx" value="BBB" />

It is expected that the button should set the slice value only on event and not during the initialization. Hence the slice-event as attribute or as immediate child tag should disable the default slot initialization. But if <slice-event> is immediate child of "slice-ed" element, and no such attribute presented, the value on element level would provide a default slice value:

<custom-element>
    <button slice="" value="AAA">
        <slice slice="clicked" slice-event="click" /> click to set AAA </button>
    <button slice="" value="BBB">
        <slice slice="clicked" slice-event="click" /> click to set BBB </button>
sashafirsov commented 4 months ago

init syntetic event when need to initialize and set another value on event

<button slice="xxx" value="AAA">
                        <!-- would set value attribute 
                           but not initialize slice 
                           as immediate slice is defined.  -->
    <slice slice-event="click" slice="xxx" value="BBB"/>
    ...
</button>

Solution:

<button slice="xxx" value="AAA"><!-- set value attribute -->
    <slice slice-event="init" slice="xxx" /> <!-- set slice, the value is taken from button -->
    <slice slice-event="click" slice="xxx" value="CCC"/>
    ...
</button>
sashafirsov commented 4 months ago

propagation of slice/value to

The slice and value attribute defined on the element level would be used by immediate <slice> child.

<button slice="//attributes/title" value="✈️" > <!-- slice is not initialized  --> 
     <slice slice-event="keydown"  /> <!-- sets `attributes/title` slice from button `value` -->
     <slice slice-event="keyup" slice-value="🪂" /><!-- sets own value -->
     <slice slice-event="click" slice-value="🚀" slice="isclicked" /> <!-- different slice, own value -->
     ... img
</button
sashafirsov commented 4 months ago

prevent slice initialization

The "action" elements like button should not change the DCE state unless acted on (clicked, etc. ). It is not expected to set the slice value. Usually the form input elements are holding the UI side source of truth.

Sample of unexpected initialization by button:

<input slice="nickname" value="anonymous" />
<button slice="nickname" value="broccoli" >🥦</button> <!-- would override initial slice value! -->

To prevent the initialization, use slice event explicitly:

<input slice="nickname" value="anonymous" />
<button slice="nickname" value="broccoli" slice-event="click tap">🥦</button> <!-- no initialization -->
sashafirsov commented 4 months ago

Tic-tac-toe sample #43 for events+slots handling