FeathersUI backend for coconut.ui

I was playing around with the @:event metadata yesterday, and I wrote a couple of helper functions for a macro I was working on. I figured I’d share, in case it might help anyone.

The first gets all of the @:event MetadataEntry values from a class and its superclasses:

private static function getAllEvents(type:ClassType):Array<MetadataEntry> {
	if (type == null) {
		return [];
	}
	var events = type.meta.extract(":event").filter(eventMeta -> eventMeta.params.length == 1);
	var superClass = type.superClass;
	if (superClass != null) {
		for (event in getAllEvents(superClass.t.get())) {
			events.push(event);
		}
	}
	return events;
}

The second gets the string value from the referenced event.

private static function getEventName(eventMeta:MetadataEntry):String {
	var typedExprDef = Context.typeExpr(eventMeta.params[0]).expr;
	return switch (typedExprDef) {
		case TCast(e, m):
			switch (e.expr) {
				case TConst(c):
					switch (c) {
						case TString(s): s;
						default: null;
					}
				default: null;
			}
		default: null;
	};
}

You can use a single switch case :wink:

switch typedExprDef {
  case TCast({expr: TConst(TString(s))}, _): s;
  case _: null;
}
5 Likes

Made changes to support new event syntax, still some things to improve but it can be used with newest git version, also made haxelib release, there is example in test folder with usage.
@joshtynjala haxelib version

1 Like

Nice work and I would love to know more about this project. From what I can tell Coconut is a vdom based UI library for Haxe that traditionally targets HTML5. This backend though will allow it to target FeatherUI which is essentially a UI layer on OpenFL.

Are the primary benefits here that this is essentially an alternative to electron for Coconut based apps?

Great, @Hersir! I hope to give it a try later this week.

I tried re-making the hello-world sample using coconut.feathersui, and it was pretty easy! Great work!

Being familiar with React, I understood the concepts already, and the coconut.ui readme had all of the syntax details that I needed.

One suggestion. I tried to create an event listener for TriggerEvent.TRIGGER, like this:

private function button_onTrigger(event:TriggerEvent):Void {}

What I found was that I had to cast the event to make it work without a compiler error:

Renderer.mount(this, '<Button text="Click Me" onTrigger={button_onTrigger(cast event)}/>');

I suspect that the macro that detects the @:event metadata can infer the correct parameter type automatically, at least some of the time.

For example, the event parameter type for the metadata below is feathers.events.TriggerEvent:

@:event(feathers.events.TriggerEvent.TRIGGER)

I’ll add one thing to watch out for, though. You should check that the class where the event is defined actually has openfl.events.Event in its inheritance chain. It might not because someone could define their own custom constant on a specific component, like this:

class MyComponent {
	public static final MY_EVENT = "myEvent";
}

Then, they would dispatch it like this:

dispatchEvent(new Event(MY_EVENT));

When constant is defined on a non-event class, then you should probably just fall back to openfl.events.Event.

This might be more of a question for @back2dos. I want to run some code before render() is called for the first time. I tried to create a constructor for my view, but I got a “custom constructor not allowed” compiler error. There doesn’t seem to be a special lifecycle method that is called before the first render either. Did I miss something?

Nope, I never covered the use case, because I never had it, but if this is a thing, please open an issue in coconut.ui and I’ll add something (probably restricted constructor support).

1 Like

Hi @joshtynjala, thank you for checking, out will try to check issues with events, I thought I added types from event but could be missed something

1 Like

Please let me know if there’s anything else that I can do to help.

@joshtynjala sorry for big delay will check soon :slight_smile: was busy at the end of the year, also had issues with OpenFL versions could not compile project, will try to solve and then add improvements what you mentioned.

1 Like

@joshtynjala maybe you have idea how to fix this

/usr/local/lib/haxe/lib/feathersui/1,0,0-beta,2/src/feathers/events/StyleProviderEvent.hx:16: characters 8-41 : Type not found : openfl._internal.utils.ObjectPool
/usr/local/lib/haxe/lib/feathersui/1,0,0-beta,2/src/feathers/events/FeathersEvent.hx:15: characters 8-41 : Type not found : openfl._internal.utils.ObjectPool
/usr/local/lib/haxe/lib/feathersui/1,0,0-beta,2/src/feathers/events/ScrollEvent.hx:15: characters 8-41 : Type not found : openfl._internal.utils.ObjectPool
/usr/local/lib/haxe/lib/actuate/1,8,9/src/motion/actuators/FilterActuator.hx:5: characters 8-35 : You cannot access the flash package while targeting js (for flash.display.DisplayObject)
/usr/local/lib/haxe/lib/actuate/1,8,9/src/motion/Actuate.hx:5: characters 8-39 :     referenced here
/usr/local/lib/haxe/lib/feathersui/1,0,0-beta,2/src/feathers/utils/Scroller.hx:12: characters 8-22 :     referenced here
/usr/local/lib/haxe/lib/feathersui/1,0,0-beta,2/src/feathers/controls/supportClasses/BaseScrollContainer.hx:24: characters 8-31 :     referenced here
/usr/local/lib/haxe/lib/feathersui/1,0,0-beta,2/src/feathers/controls/ScrollContainer.hx:12: characters 8-60 :     referenced here

I get this error, remove haxe + haxelibs, and installed fresh but still get this one in vscode.
and when to try to build project:


Warning: Could not find template file: html5/template
Warning: Could not find template file: haxe
Warning: Could not find template file: html5/hxml
Error: Could not process argument bin/html5/haxe/debug.hxml (file not found)
Invalid character: /
The terminal process "/bin/zsh '-c', 'lime test html5 -debug --connect 6001'" terminated with exit code: 1.

will try to investigate more :slight_smile:

ok solved forgot to add openfl as dependecy

<haxelib name="openfl"/>
<haxelib name="actuate"/>

@joshtynjala started to work on the issue and have already some progress
made WIP PR here

as for now implemented custom events in the callback so correct types can be used

1 Like

@joshtynjala I finished implementation for both cases, and merged pull request, should work now, if you have any other issue feel free to add issues on github. At some point will need to clean macro code as it gets not readable :slight_smile: also not sure its most optimal way of implementation.

Will release new version on haxelib soon as well. (have some issues with credentals)

Released on Haxelib

2 Likes

The change to event types is working nicely, thanks!

Another question for you. I’m trying to use my new FormItem component, which has a public var content:DisplayObject property.

I was hoping to do something like this:

<FormItem text="User Name"
	content={
		<TextInput prompt="hello@example.com"/>
	}>

But I get this error:

coconut.feathersui.RenderResult should be Null<openfl.display.DisplayObject>
For function argument ‘attr’

Any idea how I get an actual DisplayObject from a RenderResult? Or if there’s a better way to do it with similar inline syntax?

Well, it’s gonna be a minor nightmare to make that work, but I’ll look into it: Find a way to render into properties of feathers components. · Issue #6 · MVCoconut/coconut.feathersui · GitHub

1 Like

released haxelib version 1.0.2 with @back2dos implementation

3 Likes

I just tried to check out the changes in coconut.feathersui v1.0.2, but I get the following error.

/usr/local/lib/haxe/lib/coconut,feathersui/1,0,2/src/coconut/feathersui/Children.hx:5: characters 20-62 : Type not found : coconut.ui.internal.Children

It appears to be referencing this type:

However, this type does not appear to exist in the version of coconut.ui released on Haxelib, which is currently 0.11.2.

I could possibly try installing coconut.ui from Github, but I saw that there are a lot of dependencies, and I don’t know if any of those need to be updated at the same time or not. Any advice?