Skip to content

Commit 170ce29

Browse files
committed
Use hotwire to make form dynamic via ajax
1 parent a886674 commit 170ce29

File tree

5 files changed

+98
-38
lines changed

5 files changed

+98
-38
lines changed
Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,44 @@
11
class Examples::PostsController < ApplicationController
22
def index
3-
postable = case params[:type]
3+
post = Examples::Post.new(postable: build_postable)
4+
5+
render Examples::Posts::IndexView.new(post: post)
6+
end
7+
8+
def create
9+
if params[:commit] == "Refresh"
10+
post_params = params.require(:examples_post).permit(:title)
11+
post = Examples::Post.new(post_params) do |p|
12+
p.postable = build_postable
13+
end
14+
Rails.logger.info("Post: #{post.inspect}")
15+
return render Examples::Posts::IndexView.new(post: post), status: :unprocessable_entity
16+
end
17+
18+
post = Examples::Post.new(post_create_params)
19+
20+
if post.save
21+
redirect_to :index
22+
else
23+
render Examples::Posts::IndexView.new(post: post), status: :unprocessable_entity
24+
end
25+
end
26+
27+
private
28+
29+
def post_create_params
30+
postable_attributes = (params.dig(:examples_post, :postable_type) == "Examples::Posts::Markdown") ? [:body] : [:url]
31+
params.require(:examples_post).permit(:title, :postable_type, postable_attributes: postable_attributes)
32+
end
33+
34+
def build_postable
35+
case params[:type]
436
when "link"
537
Examples::Posts::Link.new
638
when "image"
739
Examples::Posts::Image.new
840
else
941
Examples::Posts::Markdown.new
1042
end
11-
12-
post = Examples::Post.new(postable: postable)
13-
14-
render Examples::Posts::IndexView.new(post: post)
15-
end
16-
17-
def create
18-
raise params.inspect
1943
end
2044
end
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { Controller } from '@hotwired/stimulus';
2+
import debug from '../../utils/debug';
3+
4+
const console = debug('app:javascript:controllers:forms:refresh');
5+
6+
export default class extends Controller {
7+
connect() {
8+
console.log('connect');
9+
}
10+
11+
refresh() {
12+
this.element.querySelectorAll('[required]').forEach((element) => {
13+
element.required = false;
14+
});
15+
const submitButton = document.createElement('input');
16+
submitButton.type = 'submit';
17+
submitButton.name = 'commit';
18+
submitButton.value = 'Refresh';
19+
submitButton.style.display = 'none';
20+
this.element.closest('form').appendChild(submitButton);
21+
submitButton.click();
22+
}
23+
}

app/javascript/controllers/index.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ import PwaWebPushDemo from './pwa/web-push-demo';
1515
import AnalyticsCustomEvent from './analytics/custom-event';
1616
import TableOfContents from './table-of-contents';
1717

18+
import FormRefresh from './forms/refresh';
19+
1820
application.register('analytics', AnalyticsCustomEvent);
1921
application.register('code-example', CodeExample);
2022
application.register('clipboard-copy', ClipboardCopy);
@@ -24,3 +26,5 @@ application.register('pwa-installation', PwaInstallation);
2426
application.register('pwa-web-push-subscription', PwaWebPushSubscription);
2527
application.register('pwa-web-push-demo', PwaWebPushDemo);
2628
application.register('table-of-contents', TableOfContents);
29+
30+
application.register('form-refresh', FormRefresh);

app/models/examples/post.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,6 @@ class Examples::Post < ApplicationRecord
44
Examples::Posts::Link
55
Examples::Posts::Image
66
]
7+
8+
accepts_nested_attributes_for :postable
79
end

app/views/examples/posts/index_view.rb

Lines changed: 36 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
class Examples::Posts::IndexView < ApplicationView
44
include Phlex::Rails::Helpers::FormWith
55
include Phlex::Rails::Helpers::LinkTo
6+
include Phlex::Rails::Helpers::ContentFor
7+
include Phlex::Rails::Helpers::LabelTag
8+
include Phlex::Rails::Helpers::RadioButtonTag
9+
include Phlex::Rails::Helpers::TurboFrameTag
610

711
def initialize(post:)
812
@post = post
@@ -15,40 +19,43 @@ def view_template
1519
)
1620

1721
div(class: "section-content container py-gap") do
18-
div(class: "tabs") do
19-
link_to "Text", examples_posts_path
20-
link_to "Link", examples_posts_path(type: "link")
21-
link_to "Image", examples_posts_path(type: "image")
22-
end
22+
turbo_frame_tag :examples_post_form do
23+
form_with model: @post, url: examples_posts_path, method: :post, data: {controller: "form-refresh"} do |form|
24+
div(class: "tabs") do
25+
link_to "Text", url_for(type: "markdown"), class: "tab"
26+
link_to "Link", url_for(type: "link"), class: "tab"
27+
link_to "Image", url_for(type: "image"), class: "tab"
28+
end
2329

24-
form_with model: @post, url: examples_posts_path, method: :post do |form|
25-
fieldset do
26-
form.label :title
27-
form.text_field :title, placeholder: "My Post 🎸", required: true
28-
end
30+
fieldset do
31+
form.label :title
32+
form.text_field :title, placeholder: "My Post 🎸", required: false
33+
end
2934

30-
form.fields_for :postable, @post.postable do |postable_form|
31-
case @post.postable
32-
when Examples::Posts::Markdown
33-
fieldset do
34-
postable_form.label :body, "Text (Markdown)"
35-
postable_form.text_area :body, placeholder: "# This is a post about guitars 🎸", required: true
36-
end
37-
when Examples::Posts::Link
38-
fieldset do
39-
postable_form.label :url, "Link URL"
40-
postable_form.text_field :url, placeholder: "https://example.com", required: true
41-
end
42-
when Examples::Posts::Image
43-
fieldset do
44-
postable_form.label :url, "Image URL"
45-
postable_form.text_field :url, placeholder: "https://example.com/image.jpg", required: true
35+
form.hidden_field :postable_type
36+
form.fields_for :postable, @post.postable do |postable_form|
37+
case @post.postable
38+
when Examples::Posts::Markdown
39+
fieldset do
40+
postable_form.label :body, "Text (Markdown)"
41+
postable_form.text_area :body, placeholder: "# This is a post about guitars 🎸", required: false
42+
end
43+
when Examples::Posts::Link
44+
fieldset do
45+
postable_form.label :url, "Link URL"
46+
postable_form.text_field :url, placeholder: "https://example.com", required: false
47+
end
48+
when Examples::Posts::Image
49+
fieldset do
50+
postable_form.label :url, "Image URL"
51+
postable_form.text_field :url, placeholder: "https://example.com/image.jpg", required: true
52+
end
4653
end
4754
end
48-
end
4955

50-
fieldset do
51-
form.submit "Save", class: "button primary"
56+
fieldset do
57+
form.submit "Save", class: "button primary"
58+
end
5259
end
5360
end
5461
end

0 commit comments

Comments
 (0)