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

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

新規登録して質問してみよう
ただいま回答率
85.47%
Ruby on Rails 6

Ruby on Rails 6は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

1回答

3623閲覧

FormData()にUncaught TypeErrorが出てしまう

tamagokake

総合スコア33

Ruby on Rails 6

Ruby on Rails 6は、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2022/02/19 03:49

編集2022/02/19 11:41

前提・実現したいこと

jQueryを使わずに非同期通信でデータベース内のデータの変更をしたいです。
編集ボタンを押すとデータを変更するためのフォームと変更ボタンが表示されるようにしました。フォームに変更内容を入力し変更ボタンを押すことでデータベース内のデータの変更を保存されフォームが非表示になり変更した内容が表示されるようにしたいです。
webアプリケーションはRailsを使っています。
初心者なので至らない点が多く見られると思いますがご教示願います。

発生している問題・エラーメッセージ

変更ボタンをクリックするとデータは変更されずに、フォームが非表示となり元のデータが表示されてしまいます。コンソールには

edit.js:53 Uncaught TypeError: Failed to construct 'FormData': parameter 1 is not of type 'HTMLFormElement'. at HTMLButtonElement.<anonymous>

と表示されています。

該当のソースコード

js

1window.addEventListener('turbolinks:load', () => { 2 const corporateEditButton = document.getElementById("js-edit-corporate-btn"); 3 corporateEditButton.addEventListener("click", () => { 4 const corporateListTitle = document.getElementById("js-corporate-label") 5 var corporateLabelArea = document.getElementsByClassName("corporate-data") 6 var corporateTextArea = document.getElementsByClassName("corporate-text") 7 const corporateName = document.getElementById("js-corporate-name") 8 const corporateButton = document.getElementById("js-corporate-button") 9 const corporateFormButton = document.getElementById("button-box") 10 for(let i = 0; i < 13; i++) { 11 corporateFormButton.style.display = "none"; 12 corporateListTitle.style.display = "none"; 13 corporateLabelArea[i].style.display = "none"; 14 corporateTextArea[i].style.display = "block"; 15 corporateName.style.display = "block"; 16 corporateButton.style.display = "block"; 17 } 18 }); 19 20 const corporateCancelButton = document.getElementById("cancel-id"); 21 corporateCancelButton.addEventListener("click", () => { 22 const corporateListTitle = document.getElementById("js-corporate-label") 23 var corporateLabelArea = document.getElementsByClassName("corporate-data") 24 var corporateTextArea = document.getElementsByClassName("corporate-text") 25 const corporateName = document.getElementById("js-corporate-name") 26 const corporateButton = document.getElementById("js-corporate-button") 27 const corporateFormButton = document.getElementById("button-box") 28 for(let i = 0; i < 13; i++) { 29 corporateFormButton.style.display = "block"; 30 corporateListTitle.style.display = "block"; 31 corporateLabelArea[i].style.display = "block"; 32 corporateTextArea[i].style.display = "none"; 33 corporateName.style.display = "none"; 34 corporateButton.style.display = "none"; 35 } 36 }); 37 38 const corporateSaveButton = document.getElementById("save-id"); 39 corporateSaveButton.addEventListener("click", () => { 40 const corporateListTitle = document.getElementById("js-corporate-label") 41 var corporateLabelArea = document.getElementsByClassName("corporate-data") 42 var corporateTextArea = document.getElementsByClassName("corporate-text") 43 44 const corporateName = document.getElementById("js-corporate-name") 45 const corporateButton = document.getElementById("js-corporate-button") 46 const corporateFormButton = document.getElementById("button-box") 47 const corporateId = document.getElementById("js-corporate-id") 48 49 50 51 for(let i = 0; i < 13; i++) { 52 var corporateText = new FormData(corporateTextArea[i]); 53 var request = new XMLHttpRequest(); 54 request.append(corporateText[i]); 55 request.open("PATCH", "/corporates/"+corporateId.value, true); 56 request.send("@corporate="+corporateText); 57 corporateFormButton.style.display = "block"; 58 corporateListTitle.style.display = "block"; 59 corporateLabelArea[i].style.display = "block"; 60 corporateTextArea[i].style.display = "none"; 61 corporateName.style.display = "none"; 62 corporateButton.style.display = "none"; 63 } 64 }); 65});

html

1<input style="display: none;" id="js-corporate-id" value=<%= @corporate.id %>> 2<div class='main'> 3 <div class='corporate-show'> 4 <div class='list-title-show'> 5 <h2 id='js-corporate-label'> 6 <%= @corporate.name %> 7 </h2> 8 <div id="js-textarea-corporate" class="list-title-edit"> 9 <input style="display: none;" id="js-corporate-name" class="corporate-text-title" value=<%= @corporate.name %>> 10 </div> 11 </div> 12 <div class='corporate-info'> 13 <p class='corporate-data'> 14 <%= @corporate.industry %> 15 </p> 16 <input style="display: none;" class="corporate-text" value=<%= @corporate.industry %>> 17 <p class='corporate-data'> 18 <%= @corporate.capital %> 19 </p> 20 <input style="display: none;" class="corporate-text" value=<%= @corporate.capital %>> 21 <p class='corporate-data'> 22 <%= @corporate.earnings %> 23 </p> 24 <input style="display: none;" class="corporate-text" value=<%= @corporate.earnings %>> 25 <p class='corporate-data'> 26 <%= @corporate.employee %> 27 </p> 28 <input style="display: none;" class="corporate-text" value=<%= @corporate.employee %>> 29 <p class='corporate-data'> 30 <%= @corporate.place %> 31 </p> 32 <input style="display: none;" class="corporate-text" value=<%= @corporate.place %>> 33 <p class='corporate-data'> 34 <%= @corporate.others %> 35 </p> 36 <input style="display: none;" class="corporate-text" value=<%= @corporate.others %>> 37 <div id="button-box"> 38 <div class='form-btn-box'> 39 <span class="form-btn", id="js-edit-corporate-btn">編集</span> 40 <%=link_to 'もどる', root_path, class:"back-btn" %> 41 </div> 42 </div> 43 <div class='form-btn-box' id="js-corporate-button" style="display: none;"> 44 <button data-update type="submit" id = "save-id" class="form-btn">変更</button> 45 <button data-cancel type="button" id = "cancel-id" class="edit-back-btn">キャンセル</button> 46 </div> 47 </div> 48 </div> 49</div>

ruby

1class CorporatesController < ApplicationController 2 def index 3 @corporates = Corporate.all 4 end 5 6 def new 7 @corporate = Corporate.new 8 end 9 10 def create 11 @corporate = Corporate.create(corporate_params) 12 if @corporate.save 13 redirect_to root_path 14 else 15 render :new 16 end 17 end 18 19 def show 20 @corporate = Corporate.find(params[:id]) 21 end 22 23 def update 24 @corporate = Corporate.find(params[:id]) 25 if @corporate.update(corporate_params) 26 render json:{ corporate: @corporate } 27 redirect_to corporate_path(@corporate.id) 28 end 29 end 30 31 private 32 33 def corporate_params 34 params.require(:corporate).permit(:name, :industry, :capital, :earnings, :employee, :place, :others) 35 end 36end

試したこと

エラー文を翻訳したのですが、理解できませんでした。

パラメーター1はタイプ 'HTMLFormElement'ではありません。

数日間苦戦しているので何かご助言をいただきたいです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

Railsに対してAjaxリクエストを投げる場合、CSRF対策のトークンを組み込む必要があります。

rails-ujsを使う場合は自動処理してくれますが、自分でXMLHTTPRequestやfetchを呼ぶ場合には自分で送信しなければいけません。

投稿2022/02/19 04:32

maisumakun

総合スコア145201

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tamagokake

2022/02/19 05:12

ユーザー登録のないメモアプリなのですがCSRF対策必要なのでしょうか? CSRFについての知識が薄く、先程検索して「ログインしているアカウントを使って悪用すること」だと把握したのですが、間違った理解の仕方をしていましたらご指摘お願いいたします。
maisumakun

2022/02/19 05:16

> ユーザー登録のないメモアプリなのですがCSRF対策必要なのでしょうか? 必要ないなら「コントローラーで外す」という選択肢もありです。デフォルトでは適用されています。
tamagokake

2022/02/19 06:15

コントローラーで外すというのはrails-ujsの話でしょうか? 検索の仕方が悪いのかもしれないのですが、rails-ujs外し方が分からないです。 また、このrails-ujsとsend()に422 (Unprocessable Entity)のエラーが出てしまうこととはどのように関わっているのでしょうか? 私の勉強不足に問題があるのは重々承知なのですが、何かご助言を頂きたいです。
maisumakun

2022/02/19 06:20

> コントローラーで外すというのはrails-ujsの話でしょうか? いえ、Railsのコード(Ruby)の問題です。 > rails-ujsとsend()に422 (Unprocessable Entity)のエラーが出てしまうこととはどのように関わっているのでしょうか? 何もしなければ422になるところ、rails-ujsにはCSRFトークンの送信処理が組み込んであるので、何も考えずに使ってもエラーにならない、という話です。
maisumakun

2022/02/19 06:21

Railsでは、JavaScript に何を使うかとは関係なく、「最初から」CSRF対策のコードが有効化されています。
tamagokake

2022/02/19 06:49

> 何もしなければ422になるところ、rails-ujsにはCSRFトークンの送信処理が組み込んであるので、何も考えずに使ってもエラーにならない、という話です。 ということはCSRFトークンの送信処理と今回のエラーとは関係がないということでしょうか? また、RailsでのCSRFトークン無効化を検索すると「検証の制御」とあるのですが検証を無効化することとトークンを無効化は同じなのでしょうか?
maisumakun

2022/02/19 06:51

> CSRFトークンの送信処理と今回のエラーとは関係がないということでしょうか? いえ、トークンを送信「していないから」422になる、という話です。
tamagokake

2022/02/19 07:20

protect_from_forgery except: :update を追記しトークンを無効化しました。 ですが同じくrequest.send("corporate="+corporateTextArea.value);でPATCH http://localhost:3000/corporates/10 400 (Bad Request)のエラーが出てしまいました。 やはりトークンとは別にsend()に問題があるのでしょうか?それともトークンの無効化ができていないのでしょうか?
maisumakun

2022/02/19 08:05

Content-typeは何を意図していますか?
tamagokake

2022/02/19 08:15

フォームに入力した内容なので、テキストファイルだと考えています。
maisumakun

2022/02/19 09:10

ただ、受け取る側がparams.require(:corporate).permitというコードになっている以上、それを踏まえたデータを送信しなければ正しく受け取れません。 受信側のコードをそのままにしたいなら、application/x-www-form-urlencoded、multipart/form-dataのどちらかの形式で送る必要があります。
tamagokake

2022/02/19 09:24

> ただ、受け取る側がparams.require(:corporate).permitというコードになっている以上、それを踏まえたデータを送信しなければ正しく受け取れません。 params.require(:corporate).permitを踏まえたデータというのはどういったことでしょうか?現在受け取ろうとしているデータの形式とは全く異なるのですか? また、application/x-www-form-urlencoded、multipart/form-dataの形式はどのように指定できるのでしょうか? 検索して出る内容でしたら調べ方などを教えていただきたいです。
maisumakun

2022/02/19 09:31

> 現在受け取ろうとしているデータの形式とは全く異なるのですか? はい、単なるテキストではなく、それ相応の構造を持たせないといけません。 > application/x-www-form-urlencoded、multipart/form-dataの形式はどのように指定できるのでしょうか? 手っ取り早いのは、URLSearchParamsやFormDataを使うことです。
tamagokake

2022/02/19 10:11

ありがとうございます。FormDataを質問内のjsファイルのように追記しましたが、 Uncaught TypeError: Failed to construct 'FormData': parameter 1 is not of type 'HTMLFormElement'. at HTMLButtonElement.<anonymous> エラーが出てしまいました。
maisumakun

2022/02/19 11:05

FormDataに文字列を組み込みたい場合、new FormData()で作成してからappendする必要があります。
tamagokake

2022/02/19 11:44

append()を検索し見よう見まねで質問内のjsファイルのように追記しましたが、エラー文に変化はありませんでした。FormDataで取得したものを代入したのですが、代入しているものが間違っているのでしょうか?
maisumakun

2022/02/19 12:18

new FormData()と、カッコの中は空にしてください。
maisumakun

2022/02/19 12:22

(teratail経由で逐一聞かなければいけないという状況は非効率でしょうし、随時連絡の取れる指導者を探したほうがいいかと思います。)
maisumakun

2022/02/19 12:23

あと、最初の質問(422 Unprocessable Entity)が解決したのに、題名や中身を書き換えてゴールポストを動かし続けるのも不誠実だと考えます。
tamagokake

2022/02/19 12:47

ご指摘ありがとうございます。 違う問題が起きた場合には別の問題として新しく質問フォーマットを作った方がよいのですね。 teratailの使い方について間違った理解の仕方をしていました。申し訳ありません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.47%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問