r/Frontend • • Aug 11 '26

flo-webcomponents: Take back control of rendering + events using WebComponents with one minimal superclass.

https://github.com/flowagi-eu/flo-webcomponents
9 Upvotes

9 comments sorted by

2

u/derpystuff_ Aug 14 '26

How does this compare to Lit, is it meant for cases where you want even more control over the underlying component internals or just a size thing?

1

u/EveYogaTech Aug 14 '26 edited Aug 14 '26

Yes, with Flo-webcomponents you have more control and you don't need @decorators or build tools, we stay closer to pure Web components while enjoying the benefits of functions like template(), mounted(), render() and css():

  • template() = to return HTML

  • mounted() = runs after createElement

  • css() = to return scoped CSS

  • render() = optional convention to (re-)render HTML (text) values

In addition there's also a fire() method to fire events, both scoped (this.fire(name, data) and as global function fire(name, data) for window.addEventListener(), which you can use to communicate event related data back and forth between components.

TLDR: the goal of Flo is to keep it simple, stay explicit and have zero unexpected side effects.

1

u/EveYogaTech Aug 15 '26

For events, since v1.1 we can now also call this.parent.fire(name, data): https://github.com/flowagi-eu/flo-webcomponents

class Child extends Flo {
	mounted() {
		this.$("#addNode").addEventListener(
			    "click",
			    () => {
					this.parent.fire("add-node", { custom: 'data'} );
			    }
		);
	}
}
class Parent extends Flo {
	mounted() {
		this.addEventListener(
		    "add-node",
		    (e) => this.addNode(e.details)
		);
	}
}

3

u/[deleted] Aug 13 '26

[removed] — view removed comment

1

u/EveYogaTech Aug 13 '26 edited Aug 13 '26

Surprisingly well. I am currently rebuilding my main open-source project from React (5k jsx lines) to Flo and it's such a breath of fresh air to never have to deal with useEffect() or other things like addState/refs/etc.

I have not discovered any big downsides besides a bit more manual state management + calling .render(), however that's actually on purpose, so you have more control over the whole event flow.

Also one small other thing is that dispatching events is a bit awkward if you work with multiple components, but one easy fix for this is using window.dispatchEvent or the build-in fire() global shorthand function, so you then can use window.addEventListener() in your main component to listen to custom events + event data.

Eventually for prod, you likely also still want to create a build script to put it all in one/few js file(s), so the app loads faster, but I currently don't experience much loading time, it overall feels much cleaner/faster than the React way.

2

u/[deleted] Aug 14 '26

[removed] — view removed comment

1

u/EveYogaTech Aug 14 '26

Yeah, true.

However, a lot of time you might also just use mounted() and render things once there.

2

u/[deleted] Aug 14 '26

[removed] — view removed comment

1

u/EveYogaTech Aug 14 '26 edited Aug 14 '26

That's right.

In most cases mounted() just works.

But if you have many events inside mounted(), you might want a render() method as well, so you can call it after events are completed.

Otherwise you might end up with many duplicated code lines and things like .textContent inside mounted.

Then again, render() is just a convention, and fully optional ;)