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

Request - docs and/or support for JSX-like inclusion of own components in dsl #494

Open
reubenfirmin opened this issue Oct 21, 2023 · 3 comments

Comments

@reubenfirmin
Copy link

JSX is the part of react that everybody likes. It's too bad that Kotlin can't handle angle braces in identifiers, but that's not something that can change soon. Nevertheless, it'd be great if KVision could provide a way to get closer to the JSX flow of "build a component and include it as a tag".

Right now, the dsl that KVision provides is nice and fluent:

root("kvapp") {
            div("Hello world")
            h2("my heading")  {
                color = Color.name(BLUE)
            }
}

However, while I can make my own component with minimal boilerplate using Kotlin's init:

class MyComponent: Div() {

    init {
        h2("goodbye world")
    }
}

...this does not work in KVision's dsl:

        root("kvapp") {
            div("Hello world")
            h2("my heading") {
                color = Color.name(BLUE)
            }
            MyComponent()
        }

Instead, I have to call add(MyComponent()), which spoils the illusion of the dsl. I think it would be fine for components to have to implement a function in order to support this (rather than init, although init is nicer), but either way, would it be possible to think about a way to more seamlessly include components within the dsl in this manner? Maybe it could be done with receivers on a different entrypoint to root, so as to avoid breaking existing apps, e.g.:

    kv("kvapp") {
      div("hello world") {
          MyComponent()        
       }
    }
@rjaros
Copy link
Owner

rjaros commented Oct 21, 2023

I'm afraid Kotlin languague is not flexible enough. While you can inherit from a function type, you can't inherit from a function with a receiver type. If you have an idea how could this be implemented please share, but I can't think of any possibility.

@reubenfirmin
Copy link
Author

😬 How do you feel about code generation?

This works:

class App : Application() {
    override fun start() {
        root("kvapp") {
            div("Hello world")
            h2("my heading") {
                color = Color.name(BLUE)
            }
            myComponent()
        }
    }
}

fun Root.myComponent() {
    add(MyComponent())
}

It could be possible to generate those extension functions to Root (or Widget) based on an annotation in components. So, I could have:

@Component
class MyComponent: Div() {

    init {
        h2("goodbye world")
    }
}

A gradle task could scan for @component, and automatically create a bunch of extension functions that could be used in dsl. I think this would improve the readability of client code quite a bit.

@rjaros
Copy link
Owner

rjaros commented Oct 21, 2023

That's a nice idea :-) I'll think about it.

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

No branches or pull requests

2 participants