-
Notifications
You must be signed in to change notification settings - Fork 113
Dynamic private field access without decorators? #236
Comments
What would be the value of a field that a user-supplied template could access being private? |
You can put something which supports dynamic access in a private field: class MyEl extends HTMLElement {
planet = 'Pluto'
#_ = { person = 'John' }
render() {
let props = this.template.getBindings() // ['planet', '#person']
let state = {}
props.forEach(prop => {
if (prop.startsWith('#')) {
state[prop] = this.#_[prop]
} else {
state[prop] = this[prop]
}
}
this.template.update(state)
}
} |
@bakkot It is not convenient. I can write same code w/o private fields, just using Symbol let privateSymbol = Symbol()
class MyEl extends HTMLElement {
planet = 'Pluto'
[privateSymbol] = { person = 'John' }
render() {
let props = this.template.getBindings() // ['planet', '#person']
let state = {}
props.forEach(prop => {
if (prop.startsWith('#')) {
state[prop] = this[privateSymbol][prop]
} else {
state[prop] = this[prop]
}
}
this.template.update(state)
}
} This approach also works for any JS class, not only for custom elements. But the private fields were introduced to simplify such code, weren't they? |
A more realistic example: <template>
<div is-drag-over="{{#isDragOver}}" on-mouseover="{{#checkIfDroppable}}" on-mouseup="{{#dropHandler}}">
<mdi-icon icon="folder"></mdi-icon>
<div contenteditable="{{#isRenameMode}}" on-input="{{#renameInputHandler}}">{{folder.name}}</div>
<mdi-icon icon="pencil" on-click="{{#renameFolder}}"></mdi-icon>
<mdi-icon icon="delete" on-click="{{#deleteFolder}}"></mdi-icon>
</div>
</template>
<script>
class FolderElement extends HTMLElement {
folder
compact = true
#isDragOver = false
#isRenameMode = false
#renameFolder() {
this.#isRenameMode = true
}
#renameInputHandler(e) {
// ...
}
#checkIfDroppable(e) {
// ...
}
#dropHandler(e) {
// ...
}
#deleteFolder() {
// ...
}
render() {
let props = this.template.getBindings()
let state = {}
props.forEach(prop => {
if (prop.startsWith('#')) {
state[prop] = ???
} else {
state[prop] = this[prop]
}
}
this.template.update(state)
}
}
</script> |
from a realistic maintennance-perspective, i don't understand why class-methods in example above need to be private. is it so you can overload these methods in subclasses? overloading is a flawed design-pattern that makes code debugging/refactoring a nightmare as you try to figure-out which function does what when grepping/searching-and-replacing through source-code. is it because they are volatile internal-api's that will frequently change, so you don't want users depending on them? realistically, all frontend-code is volatile and subject to frequent armageddon-like rewrites. humans are terrible at predicting-in-advance what the ux of a product should be and sticking with it. is it for ... security reasons? >facepalm< |
Some frameworks are looking at custom Babel transforms to generate this kind of introspection capability. If this catches on, I can imagine making a follow-up proposal for syntax for it. However, currently, you can use a workaround as explained higher on this thread. |
I will also point out that referencing a given private field might correspond to multiple fields on an object due to subclassing, the names are purely lexical. I suppose you could have a lexical form like I think it'd just be better to wait for decorators as I feel such a proposal would at least happen no sooner than decorators anyway, and while you'd probably need to decorate each private field this would at least mean you only pay the introspection costs for fields that are actually needed by the template. |
I think this question is adequately answered in several of the above comments. Thanks for the discussion here. |
At the moment, private fields are supported in Chrome 74, but how I can use them in custom elements with declarative html templates?
For example I have custom element with declarative HTML template:
and JS class:
Here #204 is probably a solution with decorators. But decorators are far from shipping and it brings a boilerplate code, because we need to decorate every private field.
Related to HTML Template Instantiation
The text was updated successfully, but these errors were encountered: