4 ms·
You can invoke custom methods and pass in any kind of data into them. As in class SomeElement extends HTMLElement { constructor() { super(); }
by mikebelanger 1y ago
You can invoke custom methods and pass in any kind of data into them. As in
class SomeElement extends HTMLElement {
constructor() {
super();
}
someMethod(x) {
this.innerHTML = `<h1>${x}</h1>`;
}
}
// ignore registry stuff
const customElement = document.getElementById('custom-element-id');
customElement.someMethod(42);
But you won't learn that from most mainstream custom element tutorials though, for whatever reason.
- hdjrudni 1y agoThat doesn't look like it even has anything to do with custom components, that's just adding a method to a class. OOP 101.
- spankalee 1y agoAnd custom elements are just classes, so you can do that.
- mikebelanger 1y ago>just adding a method to a class. OOP 101. You're right, it is just a method call from a class. Nothing interesting or new. And that's exactly why I like it! I like me FE code as boring, unimpressive and as simple as possible.
- 90s_dev 1y ago> <h1>${x}</h1> Fine for x:string, but what about w:WebWorker?
- throwanem 1y agoPresumably I've defined a .toString() method on w that will behave as I wish when implicitly invoked to perform this coercion. If I haven't, then presumably I'll be satisfied with the inherited default behavior, which will probably look something like "<h1>[object Worker]</h1>". If I care about this extremely contrived example case, in other words, I'll do something to handle it. If I don't, I won't. If I do, it's been easy for at least 25 years now; iirc .toString() was specified in ES3, which was published in March 2000.
- 90s_dev 1y agoYeah sorry I meant how would you pass it to another GUI component like we can in React.
- throwanem 1y agoIf I want in the general case to append a child node to a parent (as here with the h1 as parent and the stringified interpolated value as child), I will in almost every case call parent.appendChild(child), where parent and child both implement Node, which is the parent class of Element. The result will correspond closely to the element tree which would be constructed by assigning a string like your example to some other element's innerHTML. (You are essentially using the browser DOM implementation as a templating engine. As sugar over a lot of createElement calls and piecewise tree construction, this isn't a terrible strategy! The JSX with which you're familiar is a more elaborate and more typesafe solution for essentially the same problem.) Similarly, these references would be from the JS perspective a POJO with lots of seriously heavy implicit "render magic," so you can use them, as with any first-class Javascript value, as function arguments parallel to but a superset of what React does with its props. See the MDN documentation on Node.appendChild (and Node, Element, HTMLElement, etc) for more: https://developer.mozilla.org/en-US/docs/Web/API/Node https://developer.mozilla.org/en-US/docs/Web/API/Node If I want to represent the state of a worker thread in the UI, a problem I first recall solving over a weekend in 2016, the way I do it will end up closely resembling the "MVC pattern," with the Worker instance as "model," the DOM element structure as "view," and a "controller" that takes a Worker and returns an element tree. Even if I'm using React to build the UI - which I have also been mostly doing for about as long - I am still going to handle this translation with a library function, even if my component actually does accept a Worker as a prop, which it actually very likely will since that will enable me to easily dispatch effects and update the UI on changes of worker state. I might define that "business logic" function alongside the component which uses it, in the same module. But React or vanilla, I won't put that logic in the UI rendering code, unless it is trivial property mapping and no more (unlikely in this case, since any interesting worker thread state updates will arrive via message events requiring the parent to keep track in some way.) Does that help clear up what I'm getting at?
- spankalee 1y agoWhat would you expect that to do, in any framework?
- MrJohz 1y agoIn React, say, I might write <MyComponent worker={worker} /> and expect the worker instance to be passed as an object to `MyComponent` as a prop. But with webcomponents, I can't do something like that. this.innerHTML = `<my-component worker="${worker}">` will just stringify the worker and pass that string to the `my-component`. To get the worker instance to be passed correctly, I'd need to do something like this.innerHTML = `<my-component>` this.firstChild.worker = worker;
- mikebelanger 1y agoSo this isn't even a question about web workers, it's a question about how to prop-drill non-string/number data through multiple layers of web-components. Tbh, I'm not sure there's a way for that. But why not just define a method in your target child component and pass the worker in there?
- MrJohz 1y agoYeah, I think the original question was a bit weirdly worded which made people focus on web workers rather than complex data in general. You can use properties (as opposed to attributes) as I demonstrated, and you can use methods like you suggest, but these are both verbose and limited, and add an extra "the component has been created but the props haven't been fully passed" state to the component you're writing. Imagine a component with maybe five different props, all of which are complex objects that need to be passed by property. That's a lot of boilerplate to work with.
- spankalee 1y agoIn what way are properties verbose and limited in your view? You can set them declaratively with a template binding in most template systems.
- tomhow 1y agoI'm late getting to this but someone emailed us to point out that your attempt at code formatting didn't quite work, so I fixed it, using the formatting markup documented here: https://news.ycombinator.com/formatdoc https://news.ycombinator.com/formatdoc. Hope that's OK!