質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.34%

【Ruby, JavaScript】掲示板アプリの非同期通信を可能にしたいです

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 105

yasunsun

score 2

前提

Ruby on Rails 6.0.0で掲示板アプリを作っています。
非同期通信でコメントを投稿できるようにしたいです。
アドバイスを頂けると嬉しいです。

実現したいこと

post.jstopicIdの値を取得したいです。
posts/index8行目の<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ページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

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" な要素の 値 を取得 です

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2021/01/16 16:17

    回答ありがとうございます。
    先ほど自己解決することができました。

    キャンセル

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%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る