Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

attribute deletion leading to deadlock #77

Open
sashafirsov opened this issue Dec 5, 2024 · 1 comment
Open

attribute deletion leading to deadlock #77

sashafirsov opened this issue Dec 5, 2024 · 1 comment
Labels
bug Something isn't working

Comments

@sashafirsov
Copy link
Member

sashafirsov commented Dec 5, 2024

Inifinite rendering is caused by omitting the attribute by outer CE when inner CE has the attribute enforced.

<custom-element tag="sample-input">
    <template>
        <attribute name="name"></attribute>
        <attribute name="value" select="//val"></attribute> <!-- internally enforced value exposed to container -->
        {$name}
        <label><input type="radio" name="{$name}" slice="val" value="🍏">Apple</label>
        <label><input type="radio" name="{$name}" slice="val" value="🍌">Banana</label>
    </template>
</custom-element>
<custom-element>
    <template>
        <form slice="cart-form" action="#sample-5" custom-validity="(//inp1 = //inp2) ?? 'pick same fruit'">
            <sample-input slice="inp1" name="inp-1"></sample-input> 

            <!-- contailner does not use `value` attribute ^^ which would be removed by attributes merge -->

            <sample-input slice="inp2" name="inp-2"></sample-input>
            <button>Next</button>
            Picked :{//inp1} and {//inp2}

            <p>{//cart-form/@validation-message}</p>
        </form>
    </template>
</custom-element>

In given sample the form does not pass value and sample-input value attribute is enforced.

@sashafirsov
Copy link
Member Author

sashafirsov commented Dec 5, 2024

Possible solutions

Brute force

approach is to mark particular attribute and avoid attribute merging and as result the re-render forcing:

<sample-input slice="inp1" name="inp-1" dce-exported-attributes="value"></sample-input>
<sample-input slice="inp1" name="inp-1" value ></sample-input> - alternative syntax

CONS: easy to forget

Attribute without value would keep its value from inner CE.

treat value as special case

As the value meant to be a primary "exported" attribute, it can be excluded from deletion when exist in inner CE.
CONS: not able to remove attribute by container. Does it really matter?

use DCE observedAttributes

to check whether attribute is enforced.

window.customElements.get('sample-input').observedAttributes ; //  ['name', 'value']

PROS: does not need custom syntax

CONS: merge performance?

CONS: observedAttributes reflect rather the watching for externally changed attributes, not internally exposed.

custom property

hardcodedAttributes and exposedAttributes internal collections actually reflecting the attributes to be adopted by external CE. Those can be exposed as dceExportedAttributes custom property on the element, a set of attribute names to be consumed only by CE attributes merging algorithm.

CONS: only internal DCE implementation. Components from other libs would not have legitimate way of exposing internally controlled attributes.

Conclusion

None of methods given transparent and simple use. The following combination promises to be DX friendly and extensible to other frameworks:

  • dceExportedAttributes for internal consumption as most DX-friendly
  • dce-exported-attributes with space-separated attribute names as declarative friendly syntax

@sashafirsov sashafirsov added the bug Something isn't working label Dec 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

1 participant