Module: ViewComponent::Slotable

Extended by:
ActiveSupport::Concern
Defined in:
lib/view_component/slotable.rb

Instance Method Summary collapse

Instance Method Details

#slot(slot_name, **args, &block) ⇒ Object

Build a Slot instance on a component, exposing it for use inside the component template.

slot: Name of Slot, in symbol form **args: Arguments to be passed to Slot initializer

For example: <%= render(SlotsComponent.new) do |component| %>

<% component.slot(:footer, class_names: "footer-class") do %>
  <p>This is my footer!</p>
<% end %>

<% end %>



82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# File 'lib/view_component/slotable.rb', line 82

def slot(slot_name, **args, &block)
  # Raise ArgumentError if `slot` does not exist
  unless slots.keys.include?(slot_name)
    raise ArgumentError.new "Unknown slot '#{slot_name}' - expected one of '#{slots.keys}'"
  end

  slot = slots[slot_name]

  # The class name of the Slot, such as Header
  slot_class = self.class.const_get(slot[:class_name])

  unless slot_class <= ViewComponent::Slot
    raise ArgumentError.new "#{slot[:class_name]} must inherit from ViewComponent::Slot"
  end

  # Instantiate Slot class, accommodating Slots that don't accept arguments
  slot_instance = args.present? ? slot_class.new(**args) : slot_class.new

  # Capture block and assign to slot_instance#content
  slot_instance.content = view_context.capture(&block).to_s.strip.html_safe if block_given?

  if slot[:collection]
    # Initialize instance variable as an empty array
    # if slot is a collection and has yet to be initialized
    unless instance_variable_defined?(slot[:instance_variable_name])
      instance_variable_set(slot[:instance_variable_name], [])
    end

    # Append Slot instance to collection accessor Array
    instance_variable_get(slot[:instance_variable_name]) << slot_instance
  else
     # Assign the Slot instance to the slot accessor
    instance_variable_set(slot[:instance_variable_name], slot_instance)
  end

  # Return nil, as this method should not output anything to the view itself.
  nil
end