Skip to content

Commit

Permalink
Merge pull request #664 from github/bmw/block-content-capture
Browse files Browse the repository at this point in the history
Ensure blocks passed to slots are captured
  • Loading branch information
joelhawksley authored Mar 15, 2021
2 parents 26f3564 + 9896496 commit 6ed4d60
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 1 deletion.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@

*Joel Hawksley*

* Fix bug where blocks passed to lambda slots will render incorrectly in certain situations.

*Blake Williams*

## 2.27.0

* Allow customization of the controller used in component tests.
Expand Down
6 changes: 5 additions & 1 deletion lib/view_component/slotable_v2.rb
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,11 @@ def set_slot(slot_name, *args, **kwargs, &block)
# Use `bind(self)` to ensure lambda is executed in the context of the
# current component. This is necessary to allow the lambda to access helper
# methods like `content_tag` as well as parent component state.
renderable_value = slot_definition[:renderable_function].bind(self).call(*args, **kwargs, &block)
renderable_value = if block_given?
slot_definition[:renderable_function].bind(self).call(*args, **kwargs) { view_context.capture(&block) }
else
slot_definition[:renderable_function].bind(self).call(*args, **kwargs)
end

# Function calls can return components, so if it's a component handle it specially
if renderable_value.respond_to?(:render_in)
Expand Down
22 changes: 22 additions & 0 deletions test/app/components/slots_v2_block_component.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<%= render SlotsV2Component.new(classes: "mt-4") do |component| %>
<%= component.title do %>
This is my title!
<% end %>
<%= component.subtitle do %>
This is my subtitle!
<% end %>
<%= component.tab do %>
Tab A
<% end %>
<%= component.tab do %>
Tab B
<% end %>
<%= component.footer(classes: "text-blue") do %>
<p>Footer part 1</p>
<p>Footer part 2</p>
<% end %>
<% end %>
5 changes: 5 additions & 0 deletions test/app/components/slots_v2_block_component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# frozen_string_literal: true

class SlotsV2BlockComponent < ViewComponent::Base
include ViewComponent::SlotableV2
end
13 changes: 13 additions & 0 deletions test/view_component/slotable_v2_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -248,4 +248,17 @@ def test_slots_without_render_block

assert_selector("h1", text: "This is my title!")
end

def test_slot_with_block_content
render_inline(SlotsV2BlockComponent.new)

assert_selector("p", text: "Footer part 1")
assert_selector("p", text: "Footer part 2")
end

def test_lambda_slot_with_missing_block
render_inline(SlotsV2Component.new(classes: "mt-4")) do |component|
component.footer(classes: "text-blue")
end
end
end

0 comments on commit 6ed4d60

Please sign in to comment.