marko icon indicating copy to clipboard operation
marko copied to clipboard

Bad id created when using "no-update" and scoped id together

Open msendlakowski opened this issue 4 years ago • 3 comments

Marko Version: x.x.x

5.1.10

Details

If you use "no-update" on a scoped form element, the id of the element isn't correct. The following marko will generate an id of "s0-0-0-13-s0-0-0-13-input1"

<input id:scoped="input1" no-update />

I don't know if this is a huge issue other than the fact that if I use a "for" tag on a label, the for tag uses "s0-0-0-13-input1", so doesn't match.

Expected Behavior

The id should be s0-0-0-13-input1 or at least should be matched by the "for".

<label for:scoped="input1">Input</label>
<input id:scoped="input1" no-update />

should generate:

<label for="s0-0-0-13-input1">Input</label>
<input id="s0-0-0-13-input1">

Actual Behavior

<label for="s0-0-0-13-input1">Input</label>
<input id="s0-0-0-13-s0-0-0-13-input1">

Possible Fix

Additional Info

Your Environment

Node v14.15..4 Chrome v88 Desktop

Steps to Reproduce

<label for:scoped="input1">Input</label>
<input id:scoped="input1" no-update />

Stack Trace

msendlakowski avatar Feb 22 '21 19:02 msendlakowski

I messed around with your repro case in Try Online, but could only conclude a few things:

  • The “Compiled (HTML)” looks like something is clearly goofy with nested _component.elId’s:

     out.w(
       `<label${_marko_attr("for", _component.elId("input1"))}>Input</label>`
     );
     // …
     out.w(
             `<input${_marko_attr(
               "id",
               _component.elId(_component.elId("input1"))
             )}>`
           );
    

    “Compiled (VDOM)” shows the same problem.

  • Adding no-update to the <label> makes the IDs match

  • I can’t seem to chain :scoped and :no-update on the same attribute, so I can’t tell if for:scoped:no-update would also make the IDs match

taylor-hunt-kr avatar Mar 07 '21 01:03 taylor-hunt-kr

The issue is in copying the attributes inside no-update modifier: https://github.com/marko-js/marko/blob/ab1d038070e1eb23323d0b790e68489ade280c3e/packages/translator-default/src/tag/attribute/modifiers/no-update.js#L21

https://github.com/marko-js/marko/blob/ab1d038070e1eb23323d0b790e68489ade280c3e/packages/marko/src/runtime/vdom/preserve-attrs.js#L6

If the no-update modifier comes first than scoped attribute has correct value:

<label for:scoped="input1">Input</label>
<input no-update id:scoped="input1" />

egavrilov avatar Feb 27 '23 01:02 egavrilov

I had the same issue, using id:scoped= and no-update directives creates a completely different id than expected.

My solution was using no-update-body instead of no-update, it worked for me for the elements I was using.

    <h2
      id:scoped="idString"
      no-update-body
    >
      ${state.initialState}
    </h2>

AndresBarreto-code avatar Jul 25 '23 02:07 AndresBarreto-code