diff --git a/docs/guide/collections.md b/docs/guide/collections.md index 426a8b939..48ae219cf 100644 --- a/docs/guide/collections.md +++ b/docs/guide/collections.md @@ -12,12 +12,10 @@ Since 2.1.0 Like [Rails partials](https://guides.rubyonrails.org/layouts_and_rendering.html#rendering-collections), it's possible to render a collection with ViewComponents, using `with_collection`: ```erb -<%# app/view/products/index.html.erb %> <%= render(ProductComponent.with_collection(@products)) %> ``` ```ruby -# app/components/product_component.rb class ProductComponent < ViewComponent::Base def initialize(product:) @product = product @@ -32,7 +30,6 @@ end Use `with_collection_parameter` to change the name of the collection parameter: ```ruby -# app/components/product_component.rb class ProductComponent < ViewComponent::Base with_collection_parameter :item @@ -47,15 +44,20 @@ end Additional arguments besides the collection are passed to each component instance: ```erb -<%# app/view/products/index.html.erb %> <%= render(ProductComponent.with_collection(@products, notice: "hi")) %> ``` ```ruby -# app/components/product_component.rb class ProductComponent < ViewComponent::Base with_collection_parameter :item + erb_template <<-ERB +
  • +

    <%= @item.name %>

    + <%= @notice %> +
  • + ERB + def initialize(item:, notice:) @item = item @notice = notice @@ -63,14 +65,6 @@ class ProductComponent < ViewComponent::Base end ``` -```erb -<%# app/components/product_component.html.erb %> -
  • -

    <%= @item.name %>

    - <%= @notice %> -
  • -``` - ## Collection counter Since 2.5.0 @@ -79,8 +73,13 @@ Since 2.5.0 ViewComponent defines a counter variable matching the parameter name above, followed by `_counter`. To access the variable, add it to `initialize` as an argument: ```ruby -# app/components/product_component.rb class ProductComponent < ViewComponent::Base + erb_template <<-ERB +
  • + <%= @counter %> <%= @product.name %> +
  • + ERB + def initialize(product:, product_counter:) @product = product @counter = product_counter @@ -88,13 +87,6 @@ class ProductComponent < ViewComponent::Base end ``` -```erb -<%# app/components/product_component.html.erb %> -
  • - <%= @counter %> <%= @product.name %> -
  • -``` - ## Collection iteration context Since 2.33.0 @@ -105,18 +97,16 @@ ViewComponent defines an iteration variable matching the parameter name above, f To access the variable, add it to `initialize` as an argument: ```ruby -# app/components/product_component.rb class ProductComponent < ViewComponent::Base + erb_template <<-ERB +
  • "> + <%= @product.name %> +
  • + ERB + def initialize(product:, product_iteration:) @product = product @iteration = product_iteration end end ``` - -```erb -<%# app/components/product_component.html.erb %> -
  • "> - <%= @product.name %> -
  • -``` diff --git a/docs/guide/conditional_rendering.md b/docs/guide/conditional_rendering.md index cb65e3630..8c4223c0b 100644 --- a/docs/guide/conditional_rendering.md +++ b/docs/guide/conditional_rendering.md @@ -30,8 +30,13 @@ or the view that renders the component: Using the `#render?` hook simplifies the view: ```ruby -# app/components/confirm_email_component.rb class ConfirmEmailComponent < ViewComponent::Base + erb_template <<-ERB + + ERB + def initialize(user:) @user = user end @@ -42,13 +47,6 @@ class ConfirmEmailComponent < ViewComponent::Base end ``` -```erb -<%# app/components/confirm_email_component.html.erb %> - -``` - ```erb <%= render(ConfirmEmailComponent.new(user: current_user)) %> ``` diff --git a/docs/guide/getting-started.md b/docs/guide/getting-started.md index e70c093db..8470f6dab 100644 --- a/docs/guide/getting-started.md +++ b/docs/guide/getting-started.md @@ -41,28 +41,25 @@ Available options to customize the generator are documented on the [Generators]( ## Implementation -A ViewComponent is a Ruby file and corresponding template file with the same base name: +A ViewComponent is a Ruby class that inherits from `ViewComponent::Base`: ```ruby -# app/components/example_component.rb class ExampleComponent < ViewComponent::Base + erb_template <<-ERB + <%= content %> + ERB + def initialize(title:) @title = title end end ``` -```erb -<%# app/components/example_component.html.erb %> -<%= content %> -``` - 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 %> @@ -82,7 +79,6 @@ Since 2.31.0 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!")) %> ``` @@ -91,7 +87,6 @@ String content can also be passed to a ViewComponent by calling `#with_content`: It's also possible to render ViewComponents in controllers: ```ruby -# app/controllers/home_controller.rb def show render(ExampleComponent.new(title: "My Title")) end @@ -102,7 +97,6 @@ _Note: Content can't be passed to a component via a block in controllers. Instea 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 diff --git a/docs/guide/templates.md b/docs/guide/templates.md index f3681a8c0..073191308 100644 --- a/docs/guide/templates.md +++ b/docs/guide/templates.md @@ -8,9 +8,28 @@ parent: How-to guide ViewComponents wrap a template (or several, if using [variants](https://guides.rubyonrails.org/layouts_and_rendering.html#the-variants-option)), defined in one of several ways: +## Inline + +Since 3.0.0 +{: .label } + +To define a template inside a component, call the `.TEMPLATE_HANDLER_template` macro: + +```ruby +class InlineErbComponent < ViewComponent::Base + erb_template <<~ERB +

    Hello, <%= @name %>!

    + ERB + + def initialize(name) + @name = name + end +end +``` + ## Sibling file -The simplest option is to place the view next to the Ruby component: +Place template file next to the component: ```console app/components @@ -82,27 +101,6 @@ end _**Note**: `call_*` methods must be public._ -## Inline - -Since 3.0.0 -{: .label } - -To define a template inside a component, call the `.TEMPLATE_HANDLER_template` macro: - -```ruby -class InlineErbComponent < ViewComponent::Base - attr_reader :name - - erb_template <<~ERB -

    Hello, <%= name %>!

    - ERB - - def initialize(name) - @name = name - end -end -``` - ## Inherited Since 2.19.0 diff --git a/docs/index.md b/docs/index.md index 40e3c7a70..84bf32926 100644 --- a/docs/index.md +++ b/docs/index.md @@ -10,26 +10,23 @@ A framework for creating reusable, testable & encapsulated view components, buil ## What's a ViewComponent? -Think of ViewComponents as an evolution of the presenter pattern, inspired by [React](https://reactjs.org/docs/react-component.html). A ViewComponent is a Ruby object and template: +Think of ViewComponents as an evolution of the presenter pattern, inspired by [React](https://reactjs.org/docs/react-component.html). A ViewComponent is a Ruby object: ```ruby -# app/components/message_component.rb class MessageComponent < ViewComponent::Base + erb_template <<-ERB +

    Hello, <%= @name %>!

    + ERB + def initialize(name:) @name = name end end ``` -```erb -<%# app/components/message_component.html.erb %> -

    Hello, <%= @name %>!

    -``` - Which is instantiated and passed to Rails' `#render`: ```erb -<%# app/views/demo/index.html.erb %> <%= render(MessageComponent.new(name: "World")) %> ``` @@ -85,7 +82,7 @@ Based on several [benchmarks](https://github.com/viewcomponent/view_component/bl The primary optimization is pre-compiling all ViewComponent templates at application boot, instead of at runtime like traditional Rails views. -For example, the `MessageComponent` template is compiled onto the Ruby object like so: +For example, the `MessageComponent` template is compiled onto the Ruby object: ```ruby # app/components/message_component.rb