WebReflection / hyperHTML

A Fast & Light Virtual DOM Alternative
ISC License
3.06k stars 112 forks source link

Numeric input with 'value' attribute in IE11 #386

Closed kerim-ar closed 4 years ago

kerim-ar commented 4 years ago

Hi We try to render numeric input with 'value' attribute, code: hyperHTML.wire()(['<input type="number" id="delay" value="','" >'], 0) but in Internet Explorer 11 we get error 1 values instead of 0 <input type="number" value=", "/>

WebReflection commented 4 years ago

Are you using a proper transpiler? if you pass a new array each time the input gets trashed and re-created, but I am not planning to fix manual ES6+ attempts, as that's not what's in production.

hyperHTML.wire()`<input type="number" id="delay" value=${0} />`

Once transpiled properly, and last time I've checked, everything works fine.

kerim-ar commented 4 years ago

This is transpiled code with babel https://babeljs.io/repl/#?browsers=&build=&builtIns=false&spec=false&loose=false&code_lz=MYewdgzgLgBAlmADgV1gXhgCwJ6IKYBOAEgCoCyAMgHQDucBeAFAJQAGAPAirFLnmgCIwyALYAjQgPgATQdLwAbAIbYpANyULk_AQBIA3gEYATAGYAvlID0APlYAoaSGCi8YKFTEhp2KksT4YNIAwphwCtKMXKjMQA&debug=false&forceAllTransforms=true&shippedProposals=false&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=module&lineWrap=false&presets=env%2Cenv&prettier=false&targets=&version=7.8.4&externalPlugins=

This is sample where i try once render numeric input and add to body. In this sample i use transpiled earlier code https://jsfiddle.net/26rmkd7u/3/ image As you can see, bug is reproduced

WebReflection commented 4 years ago

OK, the type apparently messes up IE11, which drops the intended value.

This is officially a mess.

WebReflection commented 4 years ago

So, here the thing: if I fix this, I'll cause 1 years of regressions to every other attribute that works in both Edge and IE9, IE10, and IE11.

Solution

Use an intent:

hyperHTML.define(
  'data-value',
  function (node, value) {
    node.value = value;
    return value;
  }
);

You define that once, and you can style any of your inputs as such:

hyperHTML.wire()(['<input id="delay" type="number" data-value="','">'], 0)

Please note this is needed only if you use type attribute, it's not needed in any other case.

Alternatively, you can use data-type instead, and keep the value simple:

hyperHTML.define(
  'data-type',
  function (node, value) {
    node.type = value;
    return value;
  }
);
hyperHTML.wire()(['<input id="delay" data-type="', "number", '" value="','">'], 0)

This allows you to not care about all other inputs that don't need a type.

Before transpilation, that'd look like:

hyperHTML.wire()`<input data-type="${'number'}" value=${0}>`

The Issue

If you go to a blank page with any other browser, and you type the following, you'll see the expected result:

var template = document.createElement('template');
template.innerHTML = '<input type="number" value="_dt: -0.123456%">';
console.log(template.content.childNodes[0].attributes[1].value);
// _dt: -0.123456%

If you do the same in IE11, you cannot use the native template tag, because it doesn't exist, so you need to write this:

var template = document.createElement('template');
template.innerHTML = '<input type="number" value="_dt: -0.123456%">';
console.log(template.childNodes[0].attributes[1].value);
// "" <==== empty bloody string

In few words, IE11 makes it impossible to understand where is the interpolation when it comes to input fields with a type, because it does ahead-of-time validation, and there's honestly, and literally, nothing I can do.

Thanks gosh hyperHTML has intents to define data-value, which would work out of the box, now I have to write this in the documentation/README and also inform lighterhtml users that IE11 won't work with typed attributes.

I'll never explain enough how much I hate that browser.

Unless some solution comes up, which is not just by dropping _dt: prefix from the unique ID, as there is a reason that's in like that, I don't think I can fix this.

WebReflection commented 4 years ago

Alternative

With [lighterhtml]() you wouldn't have this issue as long as you use .value=${...} instead of value=${...} (note the dot upfront)

lighterhtml.render(
  document.body,
  lighterhtml.html(['<input id="delay" type="number" .value="','">'], 0)
);

The . direct property is not part of hyperHTML, but I wonder, at this point, if it should be.

I'll think about it, at least there are workaround for both libraries.

WebReflection commented 4 years ago

@kerim-ar I've just published hyperHTML v2.32.0 which includes the same feature lighterhtml offers when it comes to attributes: the .attribute=${value} feature.

This means that you can now do the same in hyperHTML:

hyperHTML.wire()`<input type="number" .value=${0}>`

And that would work out of the box 👋

kerim-ar commented 4 years ago

Thank you