Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is attributeChangedCallback called twice?

I'm building a simple custom element, using the custom elements polyfill. I've registered an attribute to be "watched" (using observedAttributes()), and when I change the value of this attribute, the function attributeChangedCallback is called twice.

Here is the HTML code:

<my-component id="compo" foo="bar"></my-component>

<button id="myBtn">Change attribute value</button>

Here is my component definition:

class MyComponent extends HTMLElement {
  constructor() {
    super();
  }
  
  static get observedAttributes() {
    return ['foo'];
  }
  
  attributeChangedCallback(attrName, oldVal, newVal) {
    console.log('[my component] attribute', attrName, 'changed from', oldVal, 'to', newVal);
  }
}

window.customElements.define('my-component', MyComponent);

// Change value of the component attribute
$('#myBtn').click(() => $('#compo').attr('foo', 'baz'));

On that page, when I click on the button, I have the following logs in the console.log:

[my component] attribute foo changed from bar to baz

[my component] attribute foo changed from bar to baz

Why is attributeChangedCallback called twice? How can I avoid it?

The JSFiddle of this example is here: https://jsfiddle.net/czo1355c/

Thanks.

like image 984
Romain Linsolas Avatar asked Jan 18 '17 11:01

Romain Linsolas


People also ask

What is a custom element?

Custom elements allow web developers to define new HTML tags, extend existing ones, and create reusable web components. Aug 14, 2017 — Updated Sep 5, 2019.

Can you make custom HTML elements?

Customized built-in elements inherit from basic HTML elements. To create one of these, you have to specify which element they extend (as implied in the examples above), and they are used by writing out the basic element but specifying the name of the custom element in the is attribute (or property).

How do custom elements work internally?

A custom element extends HTML by allowing you to define a tag whose content is created and controlled by JavaScript code. The browser maintains a CustomElementRegistry of defined custom elements, which maps an instantiable JavaScript class to an HTML tag.


1 Answers

I reviewed your jsfiddle, and it's not actually called twice on button click, but firstly called when the <my-component id="compo" foo="bar"></my-component> is rendered, as you are setting the value of foo; and secondly when you clicked the button.

You can also debug it on jsfiddle, using developer tools, and press Ctrl+Shift+F to find and debug the function.

Screenshot

like image 50
Ikram Shah Avatar answered Sep 22 '22 23:09

Ikram Shah