File: getting-started.md

package info (click to toggle)
ruby-view-component 2.74.1-1
  • links: PTS, VCS
  • area: contrib
  • in suites: bookworm
  • size: 3,156 kB
  • sloc: ruby: 6,731; sh: 163; javascript: 10; makefile: 4
file content (127 lines) | stat: -rw-r--r-- 3,338 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
69
70
71
72
73
74
75
76
77
78
79
80
81
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
120
121
122
123
124
125
126
127
---
layout: default
title: Getting started
parent: How-to guide
nav_order: 1
---

# Getting started

## Conventions

- Components are subclasses of `ViewComponent::Base` and live in `app/components`. It's common practice to create and inherit from an `ApplicationComponent` that's a subclass of `ViewComponent::Base`.
- Component names end in -`Component`.
- Component module names are plural, as for controllers and jobs: `Users::AvatarComponent`
- Name components for what they render, not what they accept. (`AvatarComponent` instead of `UserComponent`)

## Installation

In `Gemfile`, add:

```ruby
gem "view_component"
```

## Quick start

Use the component generator to create a new ViewComponent.

The generator accepts a component name and a list of arguments:

```console
bin/rails generate component Example title

      invoke  test_unit
      create  test/components/example_component_test.rb
      create  app/components/example_component.rb
      create  app/components/example_component.html.erb
```

Available options to customize the generator are documented on the [Generators](/guide/generators.html) page.

## Implementation

A ViewComponent is a Ruby file and corresponding template file with the same base name:

```ruby
# app/components/example_component.rb
class ExampleComponent < ViewComponent::Base
  def initialize(title:)
    @title = title
  end
end
```

```erb
<%# app/components/example_component.html.erb %>
<span title="<%= @title %>"><%= content %></span>
```

Content passed to a ViewComponent as a block is captured and assigned to the `content` accessor.

Rendered in a view as:

```erb
<%# app/views/home/index.html.erb %>
<%= render(ExampleComponent.new(title: "my title")) do %>
  Hello, World!
<% end %>
```

Returning:

```html
<span title="my title">Hello, World!</span>
```

## `#with_content`

Since 2.31.0
{: .label }

String content can also be passed to a ViewComponent by calling `#with_content`:

```erb
<%# app/views/home/index.html.erb %>
<%= render(ExampleComponent.new(title: "my title").with_content("Hello, World!")) %>
```

## Rendering from controllers

It's also possible to render ViewComponents in controllers:

```ruby
# app/controllers/home_controller.rb
def show
  render(ExampleComponent.new(title: "My Title"))
end
```

_Note: Content can't be passed to a component via a block in controllers. Instead, use `with_content`. In versions of Rails < 6.1, rendering a ViewComponent from a controller doesn't include the layout._

When using turbo frames with [turbo-rails](https://github.com/hotwired/turbo-rails), set `content_type` as `text/html`:

```ruby
# app/controllers/home_controller.rb
def create
  render(ExampleComponent.new, content_type: "text/html")
end
```

### Rendering ViewComponents to strings inside controller actions

When rendering the same component multiple times for later reuse, use `render_in`:

```rb
class PagesController < ApplicationController
  def index
    # Doesn't work: triggers a `AbstractController::DoubleRenderError`
    # @reusable_icon = render IconComponent.new('close')

    # Doesn't work: renders the whole index view as a string
    # @reusable_icon = render_to_string IconComponent.new('close')

    # Works: renders the component as a string
    @reusable_icon = IconComponent.new('close').render_in(view_context)
  end
```