ViewComponent Documentation
repository·main·Indexed 25 days ago
https://github.com/viewcomponent/view_componentA Ruby on Rails framework for creating reusable, encapsulated, and testable UI components by shifting view logic from templates into dedicated Ruby classes. Includes guides on component generation, preview settings, testing with ViewComponent::TestHelpers, and best practices for organizing general-purpose versus application-specific components.
What's inside ViewComponent
- ViewComponent is a framework for building reusable, testable, and encapsulated view components in Ruby on Rails. It allows developers to move logic out of templates and into dedicated Ruby classes, improving maintainability and testability of the UI layer.
Understand the ViewComponent lifecycle
mainViewComponent operates through three distinct phases: application boot, component instantiation, and render time.
- At application boot: When a class inherits from
ViewComponent::Base, theViewComponent::Compiler.compileprocess transforms the component's template(s) into instance methods on the component class. - At component instantiation: The component's
initializemethod runs. ViewComponent performs no additional actions during this phase. - At render: When passed to
render, Rails callsrender_in, providing anActionView::Context. This context provides access to the current controller, request, and helpers.
The render sequence is:
before_renderis called (allowing logic execution after initialization but before rendering).render?is called; if it returnsfalse, rendering stops and an empty string is returned.- The template is rendered, wrapped within an
around_rendercall.
- At application boot: When a class inherits from
Explore ViewComponent libraries and frameworks
mainIf you are looking for pre-built component libraries or frameworks that integrate with ViewComponent, consider the following resources:
ViewComponent libraries
Frameworks using ViewComponent
Extend ViewComponent with extensions and tools
mainEnhance your ViewComponent development workflow using these extensions and tools:
ViewComponent extensions
- ViewComponent::Storybook - For integrating with Storybook.
- ViewComponent Contrib - Additional community contributions.
- Lookbook - A component previewer.
- ViewComponentAttributes - For managing component attributes.
Tools
- rubocop-view_component - RuboCop linting rules specifically for ViewComponent.
Test ViewComponents against rendered content
mainWhen writing tests for ViewComponents, prioritize asserting against the actual rendered output rather than testing internal instance methods. This ensures you are testing what the end user actually sees.
Use
render_inlineto perform these assertions.# good render_inline(MyComponent.new) assert_text("Hello, World!") # bad assert_equal(MyComponent.new.message, "Hello, World!")Profile ViewComponent rendering with rack-mini-profiler
mainTo see detailed breakdowns of ViewComponent rendering alongside views and partials in the
rack-mini-profilerUI, add a subscription to therender.view_componentevent in your development environment configuration.# config/environments/development.rb # Profile rendering of ViewComponents Rack::MiniProfilerRails.subscribe("render.view_component") do |_name, start, finish, _id, payload| Rack::MiniProfilerRails.render_notification_handler( Rack::MiniProfilerRails.shorten_identifier(payload[:identifier]), finish, start ) endImplement a ViewComponent
mainA ViewComponent is a Ruby class that inherits from
ViewComponent::Base. You can define anerb_templatedirectly in the class or use a separate template file. Useinitializeto accept arguments. Content passed to the component via a block is accessible through thecontentaccessor.class ExampleComponent < ViewComponent::Base erb_template <<-ERB <span title="<%= @title %>"><%= content %></span> ERB def initialize(title:) @title = title end endDefine inline templates
mainYou can define a template directly inside your component class using the
erb_templateorslim_templatemacros. This is useful for small, simple components.Note for Slim users: When using
slim_template, you must escape interpolations (e.g.,\#{name}) if you want them to be evaluated in the template context rather than the component class context.class InlineErbComponent < ViewComponent::Base erb_template <<~ERB <h1>Hello, <%= @name %>!</h1> ERB def initialize(name) @name = name end endCreate a Rails application to demonstrate a ViewComponent bug
mainWhen reporting a bug, provide a minimal Rails application that reproduces the issue. Follow these steps:
- Create a minimal Rails app:
rails new --minimal view_component-bug-replica. - Add ViewComponent:
bundle add view_component(or specify a specific version in theGemfileand runbundle install). - Generate a controller:
rails generate controller Home index. - Set the root route: Add
root to: 'home#index'to your routes. - Add the minimum amount of code necessary to reproduce the bug, ideally using the original code that caused the issue.
- Publish the repository and include the link in your bug report.
rails new --minimal view_component-bug-replica bundle add view_component rails generate controller Home index- Create a minimal Rails app:
Use component-local translations with sidecar YAML files
mainYou can define translations specific to a component by creating a sidecar YAML file in the same directory as your component.
To define a default translation, create a file named
[component_name].yml. To define translations for specific locales, create files named[component_name].[locale].yml(e.g.,example_component.en.ymlorexample_component.fr.yml).These files can be automatically generated using the component generator with the
--localeflag.# app/components/example_component.yml en: hello: "Hello world!" # app/components/example_component.en.yml en: hello: "Hello world!" # app/components/example_component.fr.yml fr: hello: "Bonjour le monde !"Render spacer components between collection items
mainSince version 3.20.0, you can provide a
:spacer_componentargument towith_collection. This component will be rendered between each item in the collection.<%= render(ProductComponent.with_collection(@products, spacer_component: SpacerComponent.new)) %>Submit a pull request
mainFollow these steps to contribute code:
- Fork and clone the repository.
- Ensure all tests pass using
appraisal-run gemfiles/*.gemfile -- bundle exec rake. - Create a new branch:
git checkout -b my-branch-name. - Implement changes and add corresponding tests.
- Important: Add an entry to the top of
docs/CHANGELOG.mdfor your changes. - Push your branch and submit a pull request.