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

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

新規登録して質問してみよう
ただいま回答率
85.35%
JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

JavaScript

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

Q&A

解決済

3回答

5127閲覧

JavaScript フォームで入力された値をJSONへ変換し、確認画面で表示したい

退会済みユーザー

退会済みユーザー

総合スコア0

JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

JavaScript

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

0グッド

1クリップ

投稿2020/09/25 11:00

前提

フォームで入力された値をJSONへ変換し、確認画面で表示するプログラムを作成しました。
JSONへ変換する理由は、データ保存のためJSON形式でAPIサーバへリクエストするためです。

質問

エラーなく動作しておりますが、コメント「フォームの値をJSONへ変換」の箇所が非効率です。
クラス属性順にフォームの値を取得していることが原因と思います。
効率的な考え方等、教えていただければと思います。

参考

JavaScript フォームの確認画面を作成したい」の続きの質問です。

ソースコード

HTML

1<!DOCTYPE html> 2<html lang="ja"> 3 4<head> 5 <meta charset="UTF-8"> 6 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 7 <title>Document</title> 8</head> 9 10<body> 11 <h3>Document</h3> 12 <div id="work"> 13 <p>入力画面</p> 14 <form> 15 <p class="text">Q1.TEXT: <input type="text" name="text1" value="hoge" /></p> 16 <p class="radio">Q2.RADIO: 17 <input type="radio" name="radio1" value="A" checked />A 18 <input type="radio" name="radio1" value="B" />B</p> 19 <p class="text">Q3.TEXT: <input type="text" name="text2" value="fuga" /></p> 20 <p class="radio">Q4.RADIO: 21 <input type="radio" name="radio2" value="A" />A 22 <input type="radio" name="radio2" value="B" checked />B 23 <input type="radio" name="radio2" value="C" />C</p> 24 <input id="button" type="button" value="確認" /> 25 </form> 26 </div> 27 28 <script> 29 // イベントを非同期で取得する (非同期コンテキストで element.observe() でイベントを待つ) 30 HTMLElement.prototype.observe = function (type) { 31 return new Promise(resolve => this.addEventListener(type, resolve, { once: true })); 32 }; 33 34 (async () => { 35 while (true) { 36 // ボタンクリックを待つ 37 await document.getElementById("button").observe("click"); 38 39 // ワークエリアを取得 40 const workArea = document.getElementById("work"); 41 42 // ワークエリアをバックアップ 43 const backup = workArea.cloneNode(true); 44 45 // ワークエリアのフォームの値を取得 46 let formValue = []; 47 const countText = document.getElementsByClassName("text").length 48 for (let i = 1; i < countText + 1; i++) { 49 formValue.push(document.getElementsByName(`text${i}`)[0].value); 50 } 51 const countRadio = document.getElementsByClassName("radio").length 52 for (let i = 1; i < countRadio + 1; i++) { 53 const data = document.getElementsByName(`radio${i}`); 54 for (var j = 0; j < data.length; j++) { 55 if (data[j].checked) { 56 formValue.push(data[j].value); 57 break; 58 } 59 } 60 } 61 62 // フォームの値をJSONへ変換 63 let formJson = new Object(); 64 formJson.Q1 = formValue[0]; 65 formJson.Q2 = formValue[2]; 66 formJson.Q3 = formValue[1]; 67 formJson.Q4 = formValue[3]; 68 console.log(formJson); 69 70 // ワークエリアを結果で書き換える 71 let html = ""; 72 for (let i = 1; i < 5; i++) { 73 html += `<p>Q${i}.` + formJson[`Q${i}`] + "</p>" 74 } 75 workArea.innerHTML = ` 76 <p>確認画面</p> 77 ${html} 78 <input id="back" type="button" value="戻る"> 79 <input id="send" type="button" value="送信"> 80 `; 81 82 // 送信ボタンがクリックされたら 83 document.getElementById("send").addEventListener("click", function () { 84 console.log("APIサーバへリクエスト"); 85 }); 86 87 // 戻るボタンのクリックを待つ 88 await document.getElementById("back").observe("click"); 89 90 // ワークエリアを戻す 91 document.body.replaceChild(backup, workArea); 92 } 93 })(); 94 </script> 95</body> 96 97</html>

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

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

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

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

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

guest

回答3

0

JSON.stringify()

  • FormDataiterable なので、Array.from() で配列に変換可能です
  • JSON.stringify() で配列からJSONに変換可能です

従って、1行でJSONに変換するコードを書けます。

FormData

ただし、フォーム情報をそのままサーバに送信する目的なら、FormData をそのまま送信する方が、サーバでJSONデコードする工程が不要になる分、効率的だと思います。

Re: berry.js さん

投稿2020/09/25 14:10

think49

総合スコア18189

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

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

退会済みユーザー

退会済みユーザー

2020/09/26 00:08

ご回答ありがとうございました。 FormData をそのまま送信する方も検討してみたいと思います。
guest

0

ベストアンサー

自己満足で回答します。

HTML

1<!DOCTYPE html> 2<html lang="ja"> 3 4<head> 5 <meta charset="UTF-8"> 6 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 7 <title>Document</title> 8</head> 9 10<body> 11 <h3>Document</h3> 12 <div id="work"> 13 <p>入力画面</p> 14 <form> 15 <p class="text">Q1.TEXT: <input type="text" name="text1" value="hoge" /></p> 16 <p class="radio">Q2.RADIO: 17 <input type="radio" name="radio1" value="A" checked />A 18 <input type="radio" name="radio1" value="B" />B</p> 19 <p class="text">Q3.TEXT: <input type="text" name="text2" value="fuga" /></p> 20 <p class="radio">Q4.RADIO: 21 <input type="radio" name="radio2" value="A" />A 22 <input type="radio" name="radio2" value="B" checked />B 23 <input type="radio" name="radio2" value="C" />C</p> 24 <input id="button" type="button" value="確認" /> 25 </form> 26 </div> 27 28 <script> 29 // イベントを非同期で取得する (非同期コンテキストで element.observe() でイベントを待つ) 30 HTMLElement.prototype.observe = function (type) { 31 return new Promise(resolve => this.addEventListener(type, resolve, { once: true })); 32 }; 33 34 (async () => { 35 while (true) { 36 // ボタンクリックを待つ 37 await document.getElementById("button").observe("click"); 38 39 // ワークエリアを取得 40 const workArea = document.getElementById("work"); 41 42 // ワークエリアをバックアップ 43 const backup = workArea.cloneNode(true); 44 45 // // ワークエリアのフォームの値を取得 46 // let formValue = []; 47 // const countText = document.getElementsByClassName("text").length 48 // for (let i = 1; i < countText + 1; i++) { 49 // formValue.push(document.getElementsByName(`text${i}`)[0].value); 50 // } 51 // const countRadio = document.getElementsByClassName("radio").length 52 // for (let i = 1; i < countRadio + 1; i++) { 53 // const data = document.getElementsByName(`radio${i}`); 54 // for (var j = 0; j < data.length; j++) { 55 // if (data[j].checked) { 56 // formValue.push(data[j].value); 57 // break; 58 // } 59 // } 60 // } 61 62 // // フォームの値をJSONへ変換 63 // let formJson = new Object(); 64 // formJson.Q1 = formValue[0]; 65 // formJson.Q2 = formValue[2]; 66 // formJson.Q3 = formValue[1]; 67 // formJson.Q4 = formValue[3]; 68 // console.log(formJson); 69 70 // // ワークエリアを結果で書き換える 71 // let html = ""; 72 // for (let i = 1; i < 5; i++) { 73 // html += `<p>Q${i}.` + formJson[`Q${i}`] + "</p>" 74 // } 75 76 const formJson = Array 77 .from(document.querySelectorAll(".text > input, .radio > input[checked]")) 78 .map(a => a.value) 79 .reduce((acc, cur, idx) => { 80 acc[`Q${idx + 1}`] = cur; 81 return acc; 82 }, Object.create(null)); 83 84 const html = Object 85 .entries(formJson) 86 .map(([key, value]) => `<p>${key}.${value}</p>`) 87 .join(""); 88 89 workArea.innerHTML = ` 90 <p>確認画面</p> 91 ${html} 92 <input id="back" type="button" value="戻る"> 93 <input id="send" type="button" value="送信"> 94 `; 95 96 // // 送信ボタンがクリックされたら 97 // document.getElementById("send").addEventListener("click", function () { 98 // console.log("APIサーバへリクエスト"); 99 // }); 100 101 // // 戻るボタンのクリックを待つ 102 // await document.getElementById("back").observe("click"); 103 104 // 送信ボタンと戻るボタンのどちらかが押されたら戻る 105 const clicked = await Promise.race([ 106 document.getElementById("send").observe("click"), 107 document.getElementById("back").observe("click") 108 ]); 109 switch (clicked.target.value) { 110 case "送信": 111 console.log("APIサーバへリクエスト"); 112 break; 113 case "戻る": 114 break; 115 } 116 117 // ワークエリアを戻す 118 document.body.replaceChild(backup, workArea); 119 } 120 })(); 121 </script> 122</body> 123 124</html> 125

投稿2020/09/25 13:54

Zuishin

総合スコア28669

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

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

Zuishin

2020/09/25 22:29

送信ボタンの方を addEventListener から observe() に変更していますが、これは Promise.race() のサンプルです。 Promise.race() は複数の Promise のうち最も早く実行されたものを採用するもので、今回は送信ボタンと戻るボタンのどちらか早く押された方のイベントを返します。 どちらが返されたかは戻り値の target プロパティを見ればわかります。今回は target プロパティにボタンが入っているので、その value つまりボタンのテキストで判別しています。 このように Promise.race() を使うと、複数の非同期コンテクストを作らなくても、複数のイベントを同時に待つことができます。 この時、押された方のボタンのイベントリスナーは {once: true} オプションによって削除されますが、押されなかった方のボタンのイベントリスナーは削除されないことに気を付けてください。 コードによってはこれがメモリリークの原因となるので、https://gist.github.com/Zuishin/6c5ae7fc66fa31db175bb034878e096d のような方法を使って明示的な削除が必要になります。 これは observe() 特有の問題ではなく、addEventListener を使っても同じ問題が生じます。 ただし、今回の場合は画面を書き換えているため、イベントリスナーが関連付けられた HTML 要素ごとガベージコレクションの対象となるのでメモリリークの心配は必要ありません。
Zuishin

2020/09/25 22:56 編集

また、画面を書き換えていない場合でも、押されたボタンのイベントリスナーはすべて削除されるので、どちらか片方のみ押し続けるようなことでもなければメモリリークの心配は要りません。 例えば大量(数十万)のボタンがある場合などにメモリリークの心配をする必要があるので、その時には明示的な削除をこころがけましょう。 もっとも、人間の押すボタンによるリークなどしれているので問題になることはないと思いますが。
退会済みユーザー

退会済みユーザー

2020/09/26 00:06

丁寧なご回答ありがとうございました。 当方環境ではradioボタンの方が取得できませんでしたが、Array.from()で効率よくできそうなので、調べてみます。
Zuishin

2020/09/26 00:13

".text > input, .radio > input[checked]" これが検索条件です。class="text" 直下の input と、class="radio" 直下の input で checked がついているものを検索しています。 CSS のセレクタで指定しますので、それを調べてみてください。
guest

0

それぞれの処理を関数に分けたらどうですか?

問題毎に答えを取得する関数
表示をリライトする関数
イベントセットする関数
回答送信処理関数
などなど...

投稿2020/09/25 12:51

geta

総合スコア241

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問