0

I have build my web component DataUint and assigned it a tag <data-uint> like this:

class DataUint extends HTMLElement
{
   ...
   set value(x) { ... }
   ...
}

customElements.define("data-uint", DataUint);

When creating and accessing a component like this:

x = document.createElement('data-uint');
x.value = 10;

the call to value indeed calls the setter method and performs its function.

However when I built-in my component in the html code:

<body>
   <data-uint id='num'></data-uint>
</body>

and trying to access/use it like this:

x = body.children[0];
x.value = 10;

the call to value sets a new property to Element that is referenced by x, but never calls the setter method of the web component. The x however refers to the correct element on the page (my component) which I verified by calling other standard Element methods. It looks like this access method is returning a generic Element ignoring specializations.

Question:

I guess I am missing some basic concept here. How do I access html-defined component from JavaScript in a way that will allow me to use its member functions?

connexo
  • 53,704
  • 14
  • 91
  • 128
WolfCoder
  • 127
  • 8
  • Please provide a more complete reproducible example – Dexygen Nov 17 '21 at 11:29
  • An example would be great since it could also be an issue with the class itself. Usually, you can use setters on custom-elements usually. – niorad Nov 17 '21 at 11:41
  • Note that body.children is undefined, it needs to be document.body.children etc. – niorad Nov 17 '21 at 11:42
  • Thank you for the feedback so far and to connexo for pointing in the correct direction. I have extended the question with the reproducible example. Please check it. – WolfCoder Nov 17 '21 at 21:59
  • **Please don't extend the original scope of your questions far beyond the initial scope. Instead, ask a new question!** Your initial question "*How do I access html-defined component from JavaScript in a way that will allow me to use its member functions?*" is definitely answered. – connexo Nov 18 '21 at 08:03

1 Answers1

2

You are probably executing x = body.children[0]; x.value = 10; before the component is defined. Also note that unless you have declared a local variable body before that code runs, body will be undefined and you probably mean to use const x = document.body.children[0];.

Add this line of code:

const x = document.body.children[0]; 
console.log(x.constructor.name);
x.value = 10;

If that gives you HTMLElement, your component isn't defined at the time. If it's not defined yet, there is no setter to execute.

To check, you can also do console.log(x.matches(':defined'));.

To fix that, either wrap your code in a DOMContentLoaded listener, or wait for the component to be defined:

customElements
  .whenDefined('data-uint')
  .then((promise) => {
    const x = document.body.children[0]; 
    console.log(x.constructor.name);
    x.value = 10;
  });
connexo
  • 53,704
  • 14
  • 91
  • 128
  • The suggested addition indeed returns ```HTMLElement```. Your explanation makes sense since the definition of ```data-uint``` isn't loaded yet. The solution still puzzles me however. My code is actually placed within the constructor of another web component (this is why it is taking me so long with reproducible demo). Can I wrap a part of my constructor in ```.then()```? – WolfCoder Nov 17 '21 at 13:23
  • You can use the suggested fix then in the constructor. As far as your initial question is concerned (and all the info it gave), I assume your question is answered, so please pick an answer and consider an upvote if the answer is helpful. Regarding how to solve the problem remaining in your actual scenario will require a new question. – connexo Nov 17 '21 at 14:48