自動的にサーバーにpostするといった内容にしたいのです。
なるほど、つまりGoogleスプレッドシートやTrelloといったサービスのように
画面を開いたユーザーが操作をしたタイミングでダイレクトに更新手続きを行って欲しいわけですね。
毎回サブミットボタンを押すなんて煩わしいですからね。
可能です。
js
1const correct=1;
2if(correct==1){
3 setTimeout(function(){
4 location="/restest"//ここでrestestにpostしたい
5 },2500);
6 }
なるほど、これは先の長い話ですね。
ざっと箇条書きにしていきます。
- イベントハンドラの学習
- フォームの値を抽出して汎用オブジェクト等に加工する
- Fetch APIの学習・理解
- Fetch APIでPOST送信を行う
- Promiseの学習
- async/await構文の学習
最低でも4までは理解しないとお話になりません。
ではいきましょう。
イベントハンドラの学習
HTML上で<scriipt>
タグが登場すると、
ブラウザはJavaScriptエンジンに中身の文字列を読ませて実行します。
このJavaScriptが動作している間、他のタグ等をDOMツリーとしてメモリ上にロードして画面に描画する処理が止まります。
なのでこのように順序を変えて無限ループを仕込むと
form部分も描画されなくなりますし、ページが操作を受け付けなくなってしまいます。
(Chromeはこういったイタズラ対策で連続でalertを表示しようとすると検知して停止してくれる作りになっています)
html
1<body>
2 <script>
3 while (true) {
4 alert("何回閉じても無駄ですよ〜");
5 }
6 </script>
7 <form action="/restest" method="post">
8 <input value="送信" type="submit">
9 <input style="display:none;" name="testname" value="testtesttest">
10 </form>
11</body>
というわけで、JavaScriptは単体では「ユーザーが○○してくれるまで待つ」事が不可能な作りになっています。
一度限り上から下まで実行して終わり。
それを解決してくれるのがイベントです。
JavaScriptは「○○の条件を達成したら実行してね」と「処理して欲しいコードを関数に包んだ物」をセットでイベントハンドラに登録します。
ブラウザはJavaScriptの実行や、DOMツリーの描画等の操作が落ち着いてきて暇になると
イベントループと呼ばれる巡回を行うようになります。
ブラウザはユーザーがマウスをちょっと動かしたりクリックしたり、キーボードで文字を入力したり……
様々なタイミングで「こういう操作があったぞ!」という通知を出します。
通知されるイベント一覧はこちら
マウスカーソルをシュッと動かすだけで何十件というイベントが通知されます。
イベントループはその通知されて流れてくるイベントを見て
「そういやこの条件で実行して欲しい関数があったな」と見つけてきて、
登録されている関数をその場で実行してくれます。
せっかくなので2の項目までやってしまいましょうか。
こんな感じになるかと思います。
html
1<body>
2 <form action="/restest" method="post">
3 <!-- input に id: user_name という情報を仕込んでおく -->
4 <input id="user_name" name="user_name" value="testtesttest">
5 <input id="user_age" name="user_age" value="18">
6 </form>
7 <script>
8 window.addEventListener("load", () => {
9 console.log("ページのロードが完了しました");
10 const elements = {
11 name: document.querySelector("#user_name"),
12 age: document.querySelector("#user_age"),
13 };
14 const user = {
15 name: elements.name.value,
16 age: elements.age.value,
17 }
18 for (let k of Object.keys(elements)) {
19 elements[k].addEventListener("change", e => {
20 console.log("変更前:", user);
21 user[k] = e.target.value;
22 console.log("変更後:", user);
23 });
24 }
25 });
26 </script>
27</body>
Fetch APIでPOST送信を行う
Fetch APIはJavaScriptが裏でこっそりHTTP通信を行い、結果を持ち帰ってくれる機能です。
これから作るサービスでは上のように何らかの処理をした際、
自動的にサーバーにpostするといった内容にしたいのです。
これはFetch APIを使えば好きなタイミングで送信できます。
ただし、Fetch APIは基本的に受け取る(method: GET)のが基本なので、POSTするのは少し工夫が必要です。
参考記事: Fetch の使用 - MDN
scriptタグの中身だけ詳しく書いていきます。
js
1 window.addEventListener("load", () => {
2 console.log("ページのロードが完了しました");
3 const elements = {
4 name: document.querySelector("#user_name"),
5 age: document.querySelector("#user_age"),
6 };
7 const user = {
8 name: elements.name.value,
9 age: elements.age.value,
10 }
11 for (let k of Object.keys(elements)) {
12 elements[k].addEventListener("change", e => {
13 console.log("変更前:", user);
14 user[k] = e.target.value;
15 console.log("変更後:", user);
16 });
17 // await 構文を有効にするにはasyncキーワードを使ったasync関数を定義する必要がある
18 elements[k].addEventListener("change", async e => {
19 console.log("変更前:", user);
20 user[k] = e.target.value;
21 // fetchの返り値はPromiseのインスタンスなのでawait構文を使うと値が帰ってくるまで待つ処理が実現する
22 await fetch('https://example.com/user', {
23 method: 'POST', // or 'PUT'
24 headers: {
25 'Content-Type': 'application/json',
26 },
27 body: JSON.stringify(user),
28 });
29 console.log("変更後:", user);
30 });
31 }
32 });
Promiseやそれを扱うasync/await前提でコードを書いているので
コードでも眺めつつゆっくり学習していってください。