Skip to content

Commit

Permalink
feat(inline): allow components to be rendered without a template file
Browse files Browse the repository at this point in the history
  • Loading branch information
rainerborene committed Mar 16, 2020
1 parent 17d87b2 commit cd86bf2
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 1 deletion.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# master

# v1.16.0

* Allow components to be rendered without a template file (aka inline component).

# v1.15.0

* Re-introduce ActionView::Component::TestHelpers.
Expand Down
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,24 @@ Which returns:
</div>
```

### Inline Component

A component can be rendered without any template file as well.

`app/components/inline_component.rb`:

```ruby
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
```

### Conditional Rendering

Components can implement a `#render?` method to determine if they should be rendered.
Expand Down
6 changes: 5 additions & 1 deletion lib/view_component/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,10 @@ def compiled?
@compiled && ActionView::Base.cache_template_loading
end

def inlined?
instance_methods(false).grep(/^call/).present? && templates.empty?
end

def compile!
compile(raise_template_errors: true)
end
Expand All @@ -167,7 +171,7 @@ def compile!
# We could in theory do this on app boot, at least in production environments.
# Right now this just compiles the first time the component is rendered.
def compile(raise_template_errors: false)
return if compiled?
return if compiled? || inlined?

if template_errors.present?
raise ViewComponent::TemplateError.new(template_errors) if raise_template_errors
Expand Down
9 changes: 9 additions & 0 deletions test/app/components/inline_component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# frozen_string_literal: true

class InlineComponent < ViewComponent::Base
def initialize(*); end

def call
text_field_tag :name
end
end
8 changes: 8 additions & 0 deletions test/view_component/view_component_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@ def test_renders_content_from_block
assert_selector("span", text: "content")
end

def test_render_without_template
render_inline(InlineComponent.new)

assert_predicate InlineComponent, :inlined?
assert_not_predicate InlineComponent, :compiled?
assert_selector("input[type='text'][name='name']")
end

def test_renders_slim_template
render_inline(SlimComponent.new(message: "bar")) { "foo" }

Expand Down

0 comments on commit cd86bf2

Please sign in to comment.