前提
Ruby on Rails 6.0.0
で掲示板アプリを作っています。
非同期通信でコメントを投稿できるようにしたいです。
アドバイスを頂けると嬉しいです。
実現したいこと
post.js
でtopicId
の値を取得したいです。
posts/index
8行目の<div class="post" data-id = <%= @topic.id %>>
からidを渡します。
・post.js 4~8行目
const posts = document.querySelectorAll(".post");
const topicId = posts.getAttribute("data-id");
const formData = new FormData(document.getElementById("form"));
const XHR = new XMLHttpRequest();
XHR.open("POST", `/topics/${topicId}/posts`, true);
発生している問題・エラーメッセージ
・post.js 4, 5行目
const posts = document.querySelectorAll(".post");
でclass = post
を取得して、
そこからconst topicId = posts.getAttribute("data-id");
でdata-id
を取得しようと試みました。
しかし、topicId
の値が取得できずコンソールにエラーが表示されます。
Uncaught TypeError: post.getAttribute is not a function
該当のソースコード
・post.js
function post() {
const submit = document.getElementById("submit");
submit.addEventListener("click", (e) => {
const posts = document.querySelectorAll(".post");
const topicId = posts.getAttribute("data-id");
const formData = new FormData(document.getElementById("form"));
const XHR = new XMLHttpRequest();
XHR.open("POST", `/topics/${topicId}/posts`, true);
XHR.responseType = "json";
XHR.send(formData);
XHR.onload = () => {
if (XHR.status != 200) {
alert(`Error ${XHR.status}: ${XHR.statusText}`);
return null;
}
const item = XHR.response.post;
const list = document.getElementById("list");
const formText = document.getElementById("comment");
const HTML = `
<div class="post">
<span class="name">
名無し
</span>
<span class="time">
${item.created_at}
</span>
<p class=comment>${item.comment}</p>
</div>`;
list.insertAdjacentHTML("beforebegin", HTML);
formText.value = "";
};
e.preventDefault();
});
}
window.addEventListener("load", post);
・posts/index.html.erb
<h1><%= link_to 'トップページ', root_path, class:"top-page" %></h1>
<div>
<h3><%= @topic.title %></h3>
</div>
<% @posts.each do |post| %>
<div class="post" data-id = <%= @topic.id %>>
<span class="name">
名無し
</span>
<span class="time">
<%= post.created_at %>
</span>
<p class=comment><%= post.comment %></p>
</div>
<% end %>
<div id="list">
</div>
<%= form_with(model: [@topic, @post], id: "form" ) do |f| %>
<div class="form-input">
<div>
<%= f.text_area :comment, class: 'form-comment', id: "comment" %>
</div>
</div>
<%= f.submit '投稿する', class: 'form-submit', id: "submit" %>
<% end %>
・controllers/posts_controller.rb
class PostsController < ApplicationController
def index
@post = Post.new
@topic = Topic.find(params[:topic_id])
@posts = @topic.posts
end
def create
@topic = Topic.find(params[:topic_id])
@post = @topic.posts.new(post_params)
if @post.save
render json:{ post: @post }
else
@posts = @topic.posts
render :index
end
end
private
def post_params
params.require(:post).permit(:comment)
end
end
・config/routes.rb
Rails.application.routes.draw do
root to: 'topics#index'
resources :topics, only: [:index, :new, :create] do
resources :posts, only: [:index, :create]
end
end
・models/post.rb
class Post < ApplicationRecord
belongs_to :topic
validates :comment, presence: true
end
・models/topic.rb
class Topic < ApplicationRecord
has_many :posts
validates :title, presence: true
end
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
+1
posts = document.querySelectorAll(".post");
だと<% @posts.each
の全postが選択されてしまうから、違うんじゃないかな
<%= f.text_area :comment,
の上に
<%= hidden_field_tag :topick_id, @topick.id %>
を追加し、
const topicId = posts.getAttribute("data-id");
に替えて
const topicId = document.getElementById("topick_id").value;
としてください。
ただし、わたし JSは弱いので、JSの方は違ってるかもしれません。
要は ID="topick_id" な要素の 値 を取得 です
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
0
自己解決できました。
変更後
・posts/index.html.erb
23行目
<div class="form-input", id="post" data-id = <%= @topic.id %>>
・post.js
4,5行目
const posts = document.getElementById("post");
const topicId = posts.getAttribute("data-id");
投稿画面に遷移するリンクのturbolinksはfalseにしました。
・参考サイト
https://qiita.com/avicii2314/items/df6d2a90aeff127d4fc0
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.34%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2021/01/16 16:17
先ほど自己解決することができました。