phlex icon indicating copy to clipboard operation
phlex copied to clipboard

Shorter `component` method

Open joeldrapper opened this issue 1 year ago • 5 comments

It might be worth either renaming the component method or giving it a short alias. A few options that come to mind:

  1. comp, com or even c
  2. render or draw
  3. view

joeldrapper avatar Jul 26 '22 07:07 joeldrapper

Another option might be to define a method for each component class name, like the Array() method.

def template
  NavComponent {
    Nav::ItemComponent "Home", "/"
    Nav::ItemComponent "About", "/about"
    Nav::ItemComponent "Contact", "/contact"
  }
end

One downside with this is you would need to use an empty set of parens if you weren't passing any arguments or blocks to the component.

def template(&)
  head { ... }
  body {
    HeaderComponent()
    content(&)
    FooterComponent()
  }
end

I think this is my favourite option so far — it looks and feels really nice — but I’m open to other suggestions.

joeldrapper avatar Jul 26 '22 07:07 joeldrapper

I'm not sure how performant it is, but you should be able to define const_missing on the Phlex::Component class such that:

def template(&)
  head { ... }
  body {
    HeaderComponent
    content(&)
    FooterComponent
  }
end

could work (with const_missing taking the name of the constant, getting the class object, and then calling () on it).

However, if that noticeably hurts performance, Component() or Component[] isn't bad.

fractaledmind avatar Jul 26 '22 14:07 fractaledmind

I’m pretty sure it won't be missing though as the constant will exist.

joeldrapper avatar Jul 26 '22 14:07 joeldrapper

Ah. I was presuming that Ruby would sort-of walk up the lexical scopes, and so if Bar was defined on the global scope, but called within a method inside of Foo, then Foo.const_missing would be called before then finding Bar in the next scope up.

However, I just did a quick test in a console and that isn't true. Disregard.

fractaledmind avatar Jul 26 '22 14:07 fractaledmind

@alexandreruban and I worked on this and got it basically finished before we realised Symbols (and method names) can't contain :.

joeldrapper avatar Jul 27 '22 20:07 joeldrapper

I wonder if we should do this to stay really consistent with ViewComponent and ActionView. I also like that you don't have to discount the first positional argument like you do with component MyComponent, actually_first_argument.

def template
  render NavComponent.new {
    render Nav::ItemComponent.new("Home", "/")
    render Nav::ItemComponent.new("About", "/about")
    render Nav::ItemComponent.new("Contact", "/contact")
  }
end

I expect removing the splat and the additional block.binding.receiver check would improve performance too.

joeldrapper avatar Aug 12 '22 17:08 joeldrapper

I tried the above and it didn't work because we can't easily capture the context for the Phlex::Block. Let's just stick with component for now.

joeldrapper avatar Aug 13 '22 15:08 joeldrapper