Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Behaviors are not recognized for existing elements #2

Open
bakura10 opened this issue Aug 23, 2021 · 7 comments
Open

Behaviors are not recognized for existing elements #2

bakura10 opened this issue Aug 23, 2021 · 7 comments
Labels

Comments

@bakura10
Copy link

Hi,

First of all, thanks for this library. I really love the concept and it is a nice, logical extensions of custom elements.

However, I found that the behaviors do not work if the element is added before the library load. The scripts we are using are automatically added as "defer" scripts to load in a non-blocking way (we do not have control over the loading mechanism of the scripts).

Is this a known issue of the library? Unfortunately if that's the case I likely won't be able to use the library, but I hope this will give some ideas to browser implementers :).

@trusktr trusktr added the bug label Feb 21, 2022
@trusktr
Copy link
Member

trusktr commented Feb 21, 2022

First of all, thanks for this library. I really love the concept and it is a nice, logical extensions of custom elements.

Hey, sorry I am replying so late! Thanks! :)

behaviors do not work if the element is added before the library load

Thanks for pointing this out!

For now, the script needs to be loaded first. (We can imagine it is like a browser API, which is supposed to exist at the beginning of the page load already).

@trusktr
Copy link
Member

trusktr commented Feb 21, 2022

This needs to run before anything else, because it does some monkey patching to be compatible with ShadowDOM:

https://github.com/lume/element-behaviors/blob/main/src/index.ts#L367

This should run before application code:

<script src="https://unpkg.com/[email protected]/dist/global.js"></script>

If any application code makes custom elements (and ShadowDOM) before this is loaded, it won't work in those cases because the lib won't be able to track the has="" attributes in the ShadowRoots.

However, if elementBehaviors.define is not working after elements are already in the DOM, then that's a bug.

@jon49
Copy link

jon49 commented Jul 25, 2022

Yes, so even putting your library first in the head and then later adding the custom local code after the html right before </body> elementBehaviors.define will not work. Everything has to be loaded before the HTML inside the body tag.

@trusktr
Copy link
Member

trusktr commented Jul 25, 2022

Hmmm. 🤔 Got a sample HTML file to reproduce it? The latest version to try with is currently <script src="https://unpkg.com/[email protected]/dist/global.js"></script>

Here is a complete HTML file with the script loaded in the head, working:

<html>
	<head>
		<script src="https://unpkg.com/[email protected]/dist/global.js"></script>

		<script>
			class ClickCounter {
				constructor(element) {
					this.element = element
					this.count = 0
				}

				connectedCallback() {
					this.render()

					this.element.addEventListener('click', () => {
						this.count++
						this.render()
					})
				}

				render() {
					this.element.textContent = `count: ${this.count}`
				}
			}

			elementBehaviors.define('click-counter', ClickCounter)

			class ClickLogger {
				constructor(element) {
					this.element = element
				}

				connectedCallback() {
					this.element.addEventListener('click', () => {
						console.log('clicked on element: ', this.element)
					})
				}
			}

			elementBehaviors.define('click-logger', ClickLogger)
		</script>
	</head>
	<body>
		<button has="click-counter click-logger"></button>
	</body>
</html>

@trusktr
Copy link
Member

trusktr commented Jul 25, 2022

@jon49 By chance are you using type=module with the script that isn't working? Maybe that's why. The behaviors need to be registered up front, and using type=module will cause the script to be deferred until later rather than executing before your content is parsed.

Working on a fix, so that any elementBehaviors.define calls make any pre-existing elements with has attributes come alive regardless of load order.

@jon49
Copy link

jon49 commented Jul 26, 2022

Yes, I guess that is what I was trying to say. Is that only when I load the behaviors before the HTML elements will the behaviors work. Otherwise they are ignored. So, good to hear you are working on the fix. Granted the way this library works depending on what you are doing it is nice to do the behaviors ahead of time :-). But I could see wanting them after the fact too if an immediate visual component is not needed.

@trusktr
Copy link
Member

trusktr commented Jul 26, 2022

Yeah, it should at least be like custom elements where we can define them later, and at the later point they will run on any pre-existing elements. A use case could be, for example, loading JS after a client-side page switch, and the JS comes in after the new elements are already in view.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants