komposable/komponent

How access the given block inside the helper

Closed this issue · 17 comments

I'm looking for using the given block to my component inside the helper. But I didn't found how to retrieve the block.

I used block_given_to_component? and that's works, but if I use @block_given_to_component.call but it returns me the content of my parent component.

Is it a missing feature? Or a mistake of usage?

I do some test by extended the ComponentHelper module like following:

module ComponentHelper
  def yield_or_property(property_name)
    if block_given_to_component?
      block_given_to_component
    elsif properties.key? property_name
      properties[property_name]
    else
      raise ArgumentError, "Missing required block component or parameter: #{property_name}"
    end
  end

  def property_or_yield(property_name)
    if properties.key? property_name
      properties[property_name]
    elsif block_given_to_component?
      block_given_to_component
    else
      raise ArgumentError, "Missing required block component or parameter: #{property_name}"
    end
  end

  private

  def block_given_to_component
    @_block_given_to_component = @block_given_to_component.yield if block_given_to_component?
  end
end

And by using this method yield_or_property(:text) into the components views.

But it returns me a LocalJumpError.

Hello @nicolas-brousse,

Can you provide a gist with your use case, I don't get it what you want to achieve.

You can use it in view with yield, and you have access to block_given_to_component? in both view and helper.

I planned to remove @block_given_to_component variable in 1.1.5 because it is not documented, but if you have an use case for keep it, let me know, I should restore it in my next PR.

Hello @florentferry,

The idea is to have component where I can pass property or block for the content like following:

# frontend/components/button/_button.html.slim
- if link?
  = link_to @href, link_attributes do
    = yield_or_property(:text)

- else
  = button_tag button_attributes do
    = yield_or_property(:text)

Usage

= c "button", text: "My button text"

or

= c "button" do
  | My button text

If I use capture_block = capture(&@block_given_to_component) if block_given_to_component? I have some wired result.
screen shot 2018-03-29 at 14 34 16

I confirm that if I just simply use yield in the view I've not this issue.

I'll give you a gist too

Its an issue on komponent. I should fix it, but let me know if that kind of usage is right for your need.

def text
  if block_given_to_component?
     yield
   else
     @text
  end
end

Yes, it is. If I can access the block content it's good.
It's the first way I tried to print the block content.

Thanks!

You can use it on master branch, let me know it is not working good.

Wired I have this error undefined method `capture' for #<Komponent::ComponentRenderer:0x00007fdc0eb70d58>.

.container(data-controller="container")
  = yield

Because of a yield usage into on of my component.

I cloned the gem locally to try to understand why.

Well I'm not sure to understand why for now. I just saw that is every times I tried to call yield in a slim component view or from my helper.

Sorry about that. I push a new version on master branch and made a test to ensure component with block given are rendering without errors.

No worries it happens. Happy to help to found this bugs :)

But still have issues with usage of yield. I tried to remove all my specific code and only use a yield in a component view. And it render this:
screenshot-2018-3-30

I'll look a bit more to be sure I didn't make a mistake.

I revert to old behavior, I think using yield instead of @block_given_to_component should fix your issue for now.

Okay. Using yield inside the view so?

Yes

 if block_given_to_component?
     yield
   else
     @text
  end

Okay, thanks.

Hello @nicolas-brousse,

You can try the expected behavior on 2.0.0.pre.1, on that branch you can use the method block_given_to_component accessible in both view and helper, which contains nil or proc if block given. You can use both yield and block_given_to_component.call to access content passed in.

Let me know if the behavior is ok for you, and if the method fits well with your needs.

Thanks @florentferry!

Looks like it works fine now!