Closed ghost closed 6 years ago
+1 for such a feature. I, too, would really love to see that.
Imagine I don't know anything about lit-html, what is it that you are missing, exactly?
With hyperHTML you can pass data
right away without ever interfering with natural/real DOM:
hyper()`<p data=${anythingYouWant_really}>hello data</p>`
is that what you are looking for?
by data you mean dataset ?, i dont think data interfiere with it... but i may be wrong... if you have get/set you can re-render the element, or on the attribute change just update based on the name and it will also render, im not sure i get what is missing
There is one easy and simple justification for this. What if I want to use custom elements built by someone that expect me to be able to pass complex data through a JavaScript property other than the data
property?
Why would I want to use a template library where custom element developers have to develop their interface to accommodate the template library instead of the other way around?
Lit-Html allows me to bind to JavaScript properties and/or attributes allowing me to use any custom element pretty much written by anyone. To use hyperHtml without this feature would mean that the only custom elements that will support binding complex data will be custom elements written pretty much specifically be used with hyperHtml.
@chrismbeckett maybe I'm missing something, but the following suggests that hyperHTML has exactly the behaviour you require:
Handling data
hyperHTML will pass data to an element as properties, as long as the property is defined on the element's prototype. Otherwise it will fallback to passing data as attributes.
@joshgillies That would be great if it was true? The documentation on the viperHTML/hyperHTML website suggests that data binding uses attributes, and that if you want to pass a raw JS object down to an element you should use the data
property (and that no JSON serialization is required).
https://viperhtml.js.org/hyperhtml/documentation/#essentials-4
@chrismbeckett what leads you to believe the statement isn't true? If I'm not mistaken, the custom-elements-everywhere repo has tests highlighting the desired behaviour within hyperHTML. https://github.com/webcomponents/custom-elements-everywhere/blob/master/libraries/hyperhtml/src/advanced-tests.js#L51
A post is missing but I'd like to clarify about data
. The reason I've chosen data
is exactly because developers knows the data-
namespace is reserved for them, but data
itself is just a regular attribute that W3C will never reserve for anything else so I think it was a safe, and semantic way, to tell developers "hey, if you need to pass data, guess what kind of special attribute I've got for ya".
back to the rest ...
That would be great if it was true?
That is true. The issue is that you took hyperHTML default attribute behavior over regular DOM nodes, where setting directly and randomly properties or objects is meaningless, confusing it with Custom Elements that provides already everything you need.
As example, I use HyperHTMLElement to simplify my life but anyone can simply use any other Custom Element based library or define own components and specify the get/set behavior.
customElements.define(
'my-own',
class extends HTMLElement {
get anything() {
return this._anything;
}
set anything(value) {
this._anything = value;
this.textContent = value.text;
}
}
);
hyperHTML(document.body)`
<my-own anything=${{text: 'hello world'}}/>`;
You can see the live demo here.
TL;DR the biggest strength of hyperHTML is that does not lock you in, it frees you from dogmas and let you do through the platform everything the platform can do.
This also should be in the docs, otherwise, people may mistakenly prefer lit-html because it's clearly shown in the latter docs how to do it.
Allowing to declaratively passing/binding not-primitive values is also one primary concern of anyone, myself included, approaching Web Components and using template literals instead of JSX.
From the docs and some quick-look to other issues, I was also deceived that using data
was the only way since I thought that hyperHTML binds using only setAttribute
and data
was the unique exception to this rule, provided by the lib.
I also took a step forward and already made a version of the Custom Element example where data is passed as object: Codepen.
customElements.define(
'h-welcome',
class HyperWelcome extends HTMLElement {
constructor(...args) {
super(...args);
this.html = hyperHTML.bind(this);
}
get user() {
return this._user;
}
set user(value) {
this._user = value;
}
connectedCallback() { this.render(); }
render() {
return this.html`<h1>Hello, ${this._user.name}</h1>`;
}
}
);
hyperHTML.bind(document.getElementById('root'))`
<h-welcome user=${{ name: 'Sara' }}></h-welcome>
<h-welcome user=${{ name: 'Cahal' }}></h-welcome>
<h-welcome user=${{ name: 'Edite' }}></h-welcome>
`;
@jiayihu some minor, but very important, suggestion
customElements.define(
'h-welcome',
class HyperWelcome extends HTMLElement {
// watch out, the correct way is the followiong one
// this would work with any kind of CE polyfill too
// which is not a hyperHTML issue but a browsers one
constructor(...args) {
const self = super(...args);
self.html = hyperHTML.bind(self);
return self;
}
get user() {
return this._user;
}
// if you want to react to changes through attributes
// just render right away when such changes happen
set user(value) {
this._user = value;
this.render();
}
render() {
return this.html`<h1>Hello, ${this._user.name}</h1>`;
}
}
);
// you don't need the redundant </close-tag>
// when there is no content inside the node
hyperHTML.bind(document.getElementById('root'))`
<h-welcome user=${{ name: 'Sara' }} />
<h-welcome user=${{ name: 'Cahal' }} />
<h-welcome user=${{ name: 'Edite' }} />
`;
if you want to react to changes through attributes just render right away when such changes happen
Ops right, I forgot it!
About the rest of comments...well I took the same code from the official example 😅
What do you think however about adding the example to both the documentation Essentials and Examples?
PR's welcome there too 😅 https://github.com/viperHTML/viperhtml.github.io
I am starting to port a collection of Polymer web components to VanillaJS with ES6 string templates. I have been evaluating hyperHTML for a while and would prefer to move forward with it vs. Lit-Html, but Lit has one significant feature - the extended Lit library can pass data bindings through JavaScript properties in addition to attributes.
Are you considering any future support in hyperHTML to using property binding rather than attribute binding?