Class: ViewComponent::SlotV2

Inherits:
Object
  • Object
show all
Includes:
WithContentHelper
Defined in:
lib/view_component/slot_v2.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from WithContentHelper

#with_content

Constructor Details

#initialize(parent) ⇒ SlotV2

Returns a new instance of SlotV2.



11
12
13
# File 'lib/view_component/slot_v2.rb', line 11

def initialize(parent)
  @parent = parent
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(symbol, *args, &block) ⇒ Object

Allow access to public component methods via the wrapper

e.g.

calling ‘header.name` (where `header` is a slot) will call `name` on the `HeaderComponent` instance.

Where the component may look like:

class MyComponent < ViewComponent::Base

has_one :header, HeaderComponent

class HeaderComponent < ViewComponent::Base
  def name
    @name
  end
end

end



89
90
91
# File 'lib/view_component/slot_v2.rb', line 89

def method_missing(symbol, *args, &block)
  @__vc_component_instance.public_send(symbol, *args, &block)
end

Instance Attribute Details

#__vc_component_instance=(value) ⇒ Object (writeonly)

Sets the attribute __vc_component_instance

Parameters:

  • value

    the value to set the attribute __vc_component_instance to.



9
10
11
# File 'lib/view_component/slot_v2.rb', line 9

def __vc_component_instance=(value)
  @__vc_component_instance = value
end

#__vc_content=(value) ⇒ Object (writeonly)

Sets the attribute __vc_content

Parameters:

  • value

    the value to set the attribute __vc_content to.



9
10
11
# File 'lib/view_component/slot_v2.rb', line 9

def __vc_content=(value)
  @__vc_content = value
end

#__vc_content_block=(value) ⇒ Object (writeonly)

Sets the attribute __vc_content_block

Parameters:

  • value

    the value to set the attribute __vc_content_block to.



9
10
11
# File 'lib/view_component/slot_v2.rb', line 9

def __vc_content_block=(value)
  @__vc_content_block = value
end

Instance Method Details

#html_safe?Boolean

Returns:

  • (Boolean)


94
95
96
# File 'lib/view_component/slot_v2.rb', line 94

def html_safe?
  to_s.html_safe?
end

#respond_to_missing?(symbol, include_all = false) ⇒ Boolean

Returns:

  • (Boolean)


98
99
100
# File 'lib/view_component/slot_v2.rb', line 98

def respond_to_missing?(symbol, include_all = false)
  defined?(@__vc_component_instance) && @__vc_component_instance.respond_to?(symbol, include_all)
end

#to_sObject

Used to render the slot content in the template

There’s currently 3 different values that may be set, that we can render.

If the slot renderable is a component, the string class name of a component, or a function that returns a component, we render that component instance, returning the string.

If the slot renderable is a function and returns a string, it is set as ‘@__vc_content` and is returned directly.

If there is no slot renderable, we evaluate the block passed to the slot and return it.



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/view_component/slot_v2.rb', line 28

def to_s
  return @content if defined?(@content)

  view_context = @parent.send(:view_context)

  if defined?(@__vc_content_block) && defined?(@__vc_content_set_by_with_content)
    raise ArgumentError.new(
      "It looks like a block was provided after calling `with_content` on #{self.class.name}, " \
      "which means that ViewComponent doesn't know which content to use.\n\n" \
      "To fix this issue, use either `with_content` or a block."
    )
  end

  @content =
    if defined?(@__vc_component_instance)
      if defined?(@__vc_content_set_by_with_content)
        @__vc_component_instance.with_content(@__vc_content_set_by_with_content)

        view_context.capture do
          @__vc_component_instance.render_in(view_context)
        end
      elsif defined?(@__vc_content_block)
        view_context.capture do
          # render_in is faster than `parent.render`
          @__vc_component_instance.render_in(view_context, &@__vc_content_block)
        end
      else
        view_context.capture do
          @__vc_component_instance.render_in(view_context)
        end
      end
    elsif defined?(@__vc_content)
      @__vc_content
    elsif defined?(@__vc_content_block)
      view_context.capture(&@__vc_content_block)
    elsif defined?(@__vc_content_set_by_with_content)
      @__vc_content_set_by_with_content
    end

  @content = @content.to_s
end