Templates
ViewComponents wrap a template (or several, if using variants), defined in one of several ways:
Sibling file
The simplest option is to place the view next to the Ruby component:
app/components
├── ...
├── example_component.rb
├── example_component.html.erb
├── ...
Subdirectory
Since 2.7.0
As an alternative, views and other assets can be placed in a subdirectory with the same name as the component:
app/components
├── ...
├── example_component.rb
├── example_component
| ├── example_component.html.erb
├── ...
To generate a component with a sidecar directory, use the --sidecar
flag:
bin/rails generate component Example title --sidecar
invoke test_unit
create test/components/example_component_test.rb
create app/components/example_component.rb
create app/components/example_component/example_component.html.erb
#call
Since 1.16.0
ViewComponents can render without a template file, by defining a call
method:
# app/components/inline_component.rb
class InlineComponent < ViewComponent::Base
def call
if active?
link_to "Cancel integration", integration_path, method: :delete
else
link_to "Integrate now!", integration_path
end
end
end
It’s also possible to define methods for Action Pack variants (phone
in this case):
class InlineVariantComponent < ViewComponent::Base
def call_phone
link_to "Phone", phone_path
end
def call
link_to "Default", default_path
end
end
Note: call_*
methods must be public.
Inline
Since 3.0.0
To define a template inside a component, include the experimental ViewComponent::InlineTemplate
module and call the .TEMPLATE_HANDLER_template
macro:
class InlineErbComponent < ViewComponent::Base
include ViewComponent::InlineTemplate
attr_reader :name
erb_template <<~ERB
<h1>Hello, <%= name %>!</h1>
ERB
def initialize(name)
@name = name
end
end
Inherited
Since 2.19.0
Component subclasses inherit the parent component’s template if they don’t define their own template.
# If MyLinkComponent doesn't define a template,
# it will fall back to the `LinkComponent` template.
class MyLinkComponent < LinkComponent
end
Rendering parent templates
Since 2.55.0
To render a parent component’s template from a subclass, call render_parent
:
<%# my_link_component.html.erb %>
<div class="base-component-template">
<% render_parent %>
</div>
Trailing whitespace
Code editors commonly add a trailing newline character to source files in keeping with the Unix standard. Including trailing whitespace in component templates can result in unwanted whitespace in the HTML, eg. if the component is rendered before the period at the end of a sentence.
To strip trailing whitespace from component templates, use the strip_trailing_whitespace
class method.
class MyComponent < ViewComponent::Base
# do strip whitespace
strip_trailing_whitespace
# don't strip whitespace
strip_trailing_whitespace(false)
end