HapticX / happyx

Macro-oriented asynchronous web-framework written in Nim with β™₯
https://hapticx.github.io/happyx/
MIT License
512 stars 17 forks source link

dereferencing components children in DSL πŸ”₯ #228

Closed quimt closed 8 months ago

quimt commented 8 months ago

In extension of the 'components are like tags', it would be good to clean up the syntax for accessing components children.

In line with #194, we can use children of TagRefs, which is not too far a leap. But now that slot is not of type TagRef, it's difficult to access children of. Within the template of a component, the 'cleanest' we can do to get something like the 1st child is something like {self.slot(self).children[1]}

For accessing children from outside a component declared with use component Blah(): "child" , it looks impossible currently. The slot cannot even be declared in this way.

Describe the solution you'd like πŸ’‘

Specifically, to make the syntax more like the syntax for TagRefs while preserving the idea of the slot as a proc that leads to a component, I'd suggest defining slot.children in the template to be the children of the slot after it has rendered to a TagRef. So probably components would have an implicit State[TagRef] to take care of the TagRef result of this proc once the slot body has been decided.

Used components could then be extended similarly, with Comp.children referring to the val of a State[TagRef] which tracks the result of rendering.

Describe alternatives you've considered πŸ’β€β™€οΈ Karax handles this by only allowing straightforward types like vNode and vComponent to be placed in the DSL, alongside calls that output vNodes. This allows defining in one place how the vComponent is actually rendered but a little more heaviness in the vDom and less potential flexibliity in the syntax. So long as development proceeds with the goal of improving on the clarity of the Karax DSL (and not losing any nice syntax), I think there is a lot of upward potential with this framework.

Ethosa commented 8 months ago

Since next commit you can use slotData as rendered slot (TagRef). Also TagRef got proc `[]`(self: TagRef, idx: int)

component Dup:
  n: int
  `template`:
    for i in 1..self.n.val:
      tDiv(style = "color:red"):
        slot
        {self.slotData[0]}

...
  "/issue221":
    Dup(4):
      "slot is {rand(99)} "
    for i in 1..4:
      tDiv(style="color:blue"): "slot is {rand(99)}"

image