WebReflection/wicked-elements

onattributechanged is not called immediately OR on attach

wasimpathan5 opened this issue · 1 comments

Please refer below code snippet,

<script>
	var myComponent = {
		init: function (event) {
			this.el = event.currentTarget;
			this.render();
		},
		render: function () {
			this.el.innerHTML = '<p>My wicked element!</p>';
		},
		onattributechanged: function (e) {
			console.log('attribute changed', e.newValue);
		}
	}

	wickedElements.define('.myClass', myComponent);

	var el = document.createElement('div');
	el.classList.add('myClass');
	document.body.appendChild(el);

	el.setAttribute('attr1', 'val1'); // Doesn't trigger attribute change

	setTimeout(function () {
		el.setAttribute('attr2', 'val2'); // Triggers attribute change
	}, 0);

</script>
<div class="myClass" attr3="val3"></div> <!-- Doesn't trigger attribute change -->

Uhm ... beside this being a regular-elements bug, and not a wicked elements one, I'm not sure I want to change anything there.

In both libraries, you have a connected event, but with wicked elements you also have an init callback, which is your entry point to do anything attributes related.

Being based on MutationObserver, nodes are always setup asynchronously, which is why you don't see the first attribute change notification when you el.setAttribute('attr1', 'val1'); right after creating the node or putting the node into the DOM.

Accordingly, since the init method would give you access to any attribute you need, and it's there to grant nothing happens before the init is called, all you should care about are changes after the init happens.

Same would be with onconnected, at that time any change you need due attributes values can be easily retrieved.

This avoids:

  • complexity of delaying all events after the init happens, since that's the init contract
  • multiple events triggered per each attribute even if there was no action needed
  • trust any synchronous behavior since the whole point here is to never block

I understand that Custom Elements would behave differently here, invoking the callback per each observed attribute, but I also would like to underline here the list of observed attributes is arbitrary and, on top of that, if an attribute never changed, invoking an onattributechanged makes literally no sense to me, so that your last expectation about the <div class="myClass" attr3="val3"></div> is IMO not correct, 'cause the DIV was created as such, and no attribute ever changed since its creation.

You could stretch this concept so that it covers also manual synchronous mutation of attributes before the node is initialized/upgraded as wickedElement, and see that you actually don't need that attribute change to happen, you just need to setup, whatever you need to setup, once through the init callback.