<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>arrow-js</title>
</head>
<body>
<div id="app"></div>
<script type='module'>
import { reactive, html } from 'https://unpkg.com/@arrow-js/[email protected]/dist/index.min.mjs';
const data = reactive({
text: 'hello',
});
html`
<div>${() => data.text}</div>
<input value="${() => data.text}" @input="${e => (data.text = e.target.value)}">
<input value="${() => data.text}" @input="${e => (data.text = e.target.value)}">
`(document.getElementById('app'))
</script>
</body>
</html>
yeah interesting. Attribute binding in arrow uses setAttribute
āĀ inputs are weird in that they have their own state with a value content attribute and a value IDL property. AFAIK the IDL property is the one that is actually displayed āĀ I wonder if we should have a few special cases where we detect if the attribute being set has an matching own property (hasOwn
) and set it accordingly.
I think in case of input and maybe textarea you need to patch that element directly by setting their internal property.
At the same time, ignore the setting through the setAttribute property, because in this case there is a small security problem (we can see the password in the attribute through the element inspector for inputs with the password type)
I would suggest such a solution, which, in addition to setting value directly to the element, also includes the correct processing of boolean attributes when they have a false value, but they are still put down, which affects, for example, html5 validation through the required attribute.
type AttributeValue = string | number | boolean;
function patchProperties(element: Element, attrName: string, attrValue: AttributeValue): boolean {
const tagName = element.tagName.toLowerCase();
const fn = specialCasesMap[tagName];
let stop = fn ? fn(element, attrName, attrValue) : false;
// check IDL props
if (Object.getPrototypeOf(element).hasOwnProperty(attrName)) {
element[attrName] = attrValue;
}
// blocking the setting of all boolean attributes, except for data-attributes or other custom attributes
if (!stop && typeof attrValue === 'boolean' && !attrName.includes('-')) {
stop = true;
}
// we give out the blocking flag for setting this attribute through setAttribute
return stop;
}
const specialCasesMap: Record<string, typeof patchProperties> = {
input: (element: HTMLInputElement, attrName: string, attrValue: AttributeValue) => {
if (attrName === 'value' && typeof attrValue === 'boolean') {
// checkbox case
element.checked = attrValue;
} else if (attrName === 'autoFocus') {
// autofocus case
element.autofocus = Boolean(attrValue);
}
return false;
},
textarea: (element: HTMLTextAreaElement, attrName: string, attrValue: AttributeValue) => {
if (attrName === 'value') {
// redirect value to innerHTML
element.innerHTML = String(attrValue);
return true;
}
return false;
},
};
Thanks for the well articulated thoughts and comprehensive code example. Overall its a good direction, a few thoughts on what this implementation should look like (in my opinion):
HTMLInputElement
, HTMLSelectElement
, HTMLTextareaElement
. All of those have a value
IDL that can be set. I dont think we should set the actual value attribute of any of these. This would fall in line with how Vue does it, but would be in contrast to React.false
removing an attribute is a personal preference of mine that I think leads to much more concise and readable code, despite being a slight deviation from . Vue 2 used to do attributes this way and it switching to false being a valid value, its been a minor pain (in my opinion) and the number of use cases where false is a desired attribute is rare, and in those cases providing the string false
is acceptable. So I donāt currently plan to change this part of the implementation āĀ opinionated as it may be.And with that said āĀ this is now published/fixed in alpha.5
Owner Name | justin-schroeder |
Repo Name | arrow-js |
Full Name | justin-schroeder/arrow-js |
Language | TypeScript |
Created Date | 2022-11-08 |
Updated Date | 2023-03-28 |
Star Count | 1240 |
Watcher Count | 21 |
Fork Count | 22 |
Issue Count | 7 |
Issue Title | Created Date | Updated Date |
---|