Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/guide/lifecycle.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ Since 2.8.0

Define a `before_render` method to be called before a component is rendered, when `helpers` is able to be used:

`before_render` is only called if `render?` returns true. Since `render?` runs first, it must not depend on state set in `before_render`.

```ruby
# app/components/example_component.rb
class ExampleComponent < ViewComponent::Base
Expand Down
5 changes: 3 additions & 2 deletions lib/view_component/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,9 @@ def render_in(view_context, **, &block)
@__vc_render_in_block = block
@view_context.instance_variable_set(:@virtual_path, virtual_path)

before_render

if render?
before_render

value = nil

@output_buffer.with_buffer do
Expand Down Expand Up @@ -239,6 +239,7 @@ def output_postamble

# Called before rendering the component. Override to perform operations that
# depend on having access to the view context, such as helpers.
# Only called if `render?` returns true.
#
# @return [void]
def before_render
Expand Down
27 changes: 27 additions & 0 deletions test/sandbox/test/rendering_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,33 @@ def test_conditional_rendering
assert_no_text("component was rendered")
end

def test_before_render_is_not_called_when_render_is_false
component = ConditionalRenderComponent.new(should_render: false)
callbacks = []
component.define_singleton_method(:before_render) { callbacks << :before_render }

render_inline(component)

assert_empty callbacks
refute_component_rendered
assert_predicate rendered_content, :html_safe?
end

def test_before_render_is_called_after_render_predicate
component = ConditionalRenderComponent.new(should_render: true)
callbacks = []
component.define_singleton_method(:render?) do
callbacks << :render?
super()
end
component.define_singleton_method(:before_render) { callbacks << :before_render }

render_inline(component)

assert_equal [:render?, :before_render], callbacks
assert_text("component was rendered")
end

def test_conditional_rendering_if_content_provided
render_inline(ConditionalContentComponent.new)

Expand Down
Loading