haxeui / haxeui-core

The core library of the HaxeUI framework
http://haxeui.org
MIT License
346 stars 71 forks source link

Clarify the state of property / data bindings #463

Open robinp opened 2 years ago

robinp commented 2 years ago

Hello! I came to see HaxeUI just now, after being spoiled by reactive frameworks for HTML (specifically Vue, but similar are React, Purescript-Halogen etc). It seems my expectations vs reality are out of sync, and can't find pointers in the documentation about what is possible and what not in HaxeUI.

First thing I was thinking: When I saw xml-based component definitions, first I expected there would be templatized loop / if constructs, to dynamically expand components based on data. As far I can tell now, that is not an option - so I guess I need to manage that manually from code.

Next thing: I though about xml, it would be possible to refer to pieces of data that I maintain from code, so the UI would get updated with the related changes (though, without xml-based looping constructs, the use of this is somewhat limited - to text properties etc). I found some old docs referring this via BindingManager, but that seems to be gone now. In the current code there are mentions of bindings (also an open issue mentioning), but not clear how one is supposed to use those.

My conclusion so far, is that if I'm interested in data-based UI updates, I would be better off managing everything from code, as the XML is not very helpful or flexible here. If that's the truth, all fine, but the docs could point this out. If this is not the truth - well, docs again.

I don't mean to be nitting, just hope the perspective of a complete newcomer to the framework helps improve the initial learning experience.

(Totally unrelated sidenote, as a bit of inspiration / background: I really like the one-way data binding used by Vue / React / Elm etc. It turns out the two-way databinding, for example what was used by Angular, was a pain to manage automatically.

So in Vue (2) for example, you can imagine to have a big bunch of data at the root, held by the root component. The root component's template (kind of like HaxeUI's xml) then binds parts of this data into properties for subcomponents. And so on, recursively.

But to manage cognitive / implementation complexity, a bound property's value (and so the related pieces of data) never changes in a bottom->up fashion. Let's say, even if you bound a piece of data to a slider's value, if the slider is moved, that piece of data is not changed. Rather, changes fire events, and one should explicitly catch events (at some parent scope), and mutate the local data. In response to that explicit mutation, somewhere down the line the bound property's value will change, but from a top->down change.

Also see the Elm architecture (https://guide.elm-lang.org/architecture/) that puts down the idea. Though I think Elm only has a single top-level state that propagates down, while in Vue/etc, components can also manage their own local data... but the idea is similar.

(Note in note: this reactivity-in-depth is made performant by using some virtual-dom mechanism, to only change those UI components whose state really changed. For example, you don't want to re-render all 1000 elements in a list just because a bound value used by a single element changed. But that needs the data binding to also provide some stable keys for list elements, so the list diffing operation can work effectively... as far I understand) )

robinp commented 2 years ago

Fun, just came through https://github.com/haxeui/haxeui-guides/blob/master/custom-components.md#using-binding, which has a pointer to @:bind usage.

robinp commented 2 years ago

Thinking bit more, a <template-if cond="{foo}"> like construct might be implementable.. and for loops, I see there's ListView together with its render template. Those should cover most of the ground. Will see their usage in practice and report back eventually.

sh-dave commented 2 years ago

Sounds like you want https://github.com/MVCoconut/coconut.ui with a haxeui backend https://github.com/MVCoconut/coconut.haxeui

ianharrigan commented 2 years ago

Hi!

So yeah, as Dave indicated, HaxeUI (out the box) doesnt really do things like this - it might be advantageous, and ive been considering a way to "slot it in" as an extra, but it might not be possible, and if it is, it wouldnt be coming anytime soon im afraid.

HaxeUI defo takes the more "traditional" approach (for better or worse). As Dave also mentioned there is a haxeui "flavour" to coconut, which is basically haxe's reactive solution to UI (for various frameworks). Ive honestly never used it myself, but i know people who have (with haxeui), there were some stumbling blocks iirc, especially with haxeui native backends (haxeui-hxwidgets), but i think alot (maybe all?) got resolved.

Binding is one aspect to haxeui, but its very "not like react", its really just a code builder that builds handlers and events for you. It can work for simple things, but for very complex things its not going to work like react (ie, you mentioned item renderers / listviews and loops/conditions in xml - which i despise btw - but its a personal pref ;) )

This might help a little about the way custom components / views work in haxeui: https://github.com/haxeui/haxeui-guides/blob/master/custom-components.md

Hope that helps somewhat! Oh, and btw, there is #haxeui channel on the #haxe discord: https://discord.com/channels/162395145352904705/565569107701923852 - it may be easier to discuss features (and limitations) there :)

Cheers, Ian

EDIT: just realised you already linked to the custom components guide, my bad :)