0

I have two separate custom element components and if I want to do something with the ComponentB's element inside of ComponentA, what is the best way to do it?

index.html

<body>

  <componentA>
    <div class="container">
     <p>I am component A</p>
     <p>abc</p>
    </div>
  </componentA>

  <componentB>
    <div class="container">
     <p>I am component B</p>
     <p></p> // Will set data between the p tag in componentA
    </div>
  </componentB>

</body>

componentA.js

...component template...

class ComponentA extends HTMLElement {

  constructor() {
    super();
    this.attachShadow({mode: 'open'});
    this.shadowRoot.appendChild(template.content.cloneNode(true));
  }

  connectedCallback() {

    this.setInnerTextToComponentBElement();

  }

  setInnerTextToComponentBElement(){

    // How to set componentB's second p tag innerText?

  }
}

customElements.define('componentA', ComponentA );

I have thought of using document.querySelector to get the componentB element and go from there... but is this the best practice way to do it?

MrBear77
  • 93
  • 2
  • 8
  • Events, like you asked for in your previous question. Note: You can pass anything in ``event.detail``, doesn't have to be data. So **A** can pass a _**A-method**_ **reference** to **B** in an Event, then **B** can execute it – Danny '365CSI' Engelman Jun 13 '20 at 09:48
  • Hi, thanks Danny, so basically what you mean is I need to dispatch the custom event to the parent(in this case is the normal DOM) and inside of componentB I'll need to catch the event using document.addEventListener()? and another small question is that is it consider bad practice to interact with other web component siblings? thanks – MrBear77 Jun 13 '20 at 11:06
  • Or make event listeners listen at document or a common parent level. You have many options. There are no bad practices, software development is art. You are the artist. – Danny '365CSI' Engelman Jun 13 '20 at 17:32

1 Answers1

1

I would suggest NEVER tying two components together without allowing the developer using the components to provide a way to connect them.

Normally communications or interconnections between elements is handled by the parent. The only element that I know of that does this by itself is the <label> element. If this is the parent of an <input>, <select>, <button> or <textarea> then it will pass its focus on to the child element.

But to use it with a sibling element you have to set the for attribute of the <label> to be the id of the other field. And then the other field needs to have its id set.

I answered something like this here: How to communicate between Web Components (native UI)?

Once you tie two components together these components are no longer usable by themselves unless you write extra code to allow separation.

Instead, either allow the components to dispatch events that the parent will receive and the parent will then pass values on to the other component. Or, follow the example of how <label for=""> works.

Intervalia
  • 10,248
  • 2
  • 30
  • 60
  • Hi, so for using the dispatch events way, you mean like inside of componentA I dispatch an custom event to the actual parent document(not the #document-fragment) and listen to the custom event inside of the componentB? – MrBear77 Jun 18 '20 at 10:40
  • Yes. Try to keep your custom components functioning the same way that built in components work. Besides the ` – Intervalia Jun 19 '20 at 14:13
  • To be fair. The elements with shadow DOM will normally dispatch their custom events using `this.dispatchEvent` so it is sent from the element container and not from a sub element in the shadow-dom. Although if you embed other elements in your shadow DOM then those will/should dispatch on their element container, etc. – Intervalia Jun 19 '20 at 14:15
  • What about can I use "document.querySelector()" to pass data to another sibling web component's property? does this count as talking to sibling directly? example: Two web component /custom element inside of the normal document(not the #document-fragment) and inside of componentA, I use document.querySelector('componentB').myData = 'random data'; to pass data to componentB. thanks – MrBear77 Jun 20 '20 at 07:54
  • Sure, You CAN do that, but should you? If you tie two components together by using a query selector then the two components ALWAYS need to be together. Now if you don't expect these components to ever be used alone or if they will never leave this page, go for it. But if you want reusability, then I suggest against it. Instead do something like the ` – Intervalia Jun 22 '20 at 20:43