Fetch API 演習
この章では教材の「Fetch API」の内容を扱っています。
課題
料理店に評価をつけられるサイトを作ってみましょう。
ヒント
選択式のメニューを作るには
select
タグを用いましょう。index.html<select id="rating-select">
<option value="5">☆5</option>
<option value="4">☆4</option>
<option value="3">☆3</option>
<option value="2">☆2</option>
<option value="1">☆1</option>
</select>option
のvalue
に入れられている数字は文字列のため、平均評価の算出をする前に数値に変換しておくと良いでしょう。以下ではNumber
オブジェクトを用いる例を示します。sample.jsconst one = "1";
const two = "2";
console.log(one + two); // 12
console.log(Number(one) + Number(two)); // 3今回は、登録されているレストランの最新の情報を取得するため一定時間ごとに画面を描画し直すことが必要ですが、そのようにすると店名を選択する
select
要素が操作できなくなってしまうことに注意が必要です。以下では、現在操作されている(フォーカスが当たっている)要素を取得するdocument.activeElement
を用いて、料理店の評価の送信に必要なselect
要素が操作されている際には再描画を行わないようにしています。script.jsif (
document.activeElement !== nameSelect &&
document.activeElement !== ratingSelect
) {
// 再描画
}
解答例
解答
server.js
app.get("/restaurants", (request, response) => {
response.json(restaurants);
});
app.post("/register", (request, response) => {
restaurants.push({
name: request.body.name,
totalRating: 0,
numRatings: 0,
averageRating: 0,
});
response.end();
});
app.post("/rate", (request, response) => {
const index = request.body.index;
restaurants[index].totalRating += Number(request.body.rating); // 文字列を数値に変換
restaurants[index].numRatings += 1;
if (restaurants[index].numRatings !== 0) {
// 評価者が0人でないときは、平均点を計算
restaurants[index].averageRating =
restaurants[index].totalRating / restaurants[index].numRatings;
} else {
// 評価者が0人のときは、平均点は0(ゼロ除算を防ぐため)
restaurants[index].averageRating = 0;
}
response.end();
});
static/script.js
setInterval(async () => {
// nameSelect にも ratingSelect にもフォーカスが当たっていない際にのみ、要素を再生成する
if (
document.activeElement !== nameSelect &&
document.activeElement !== ratingSelect
) {
const response = await fetch("/restaurants");
const restaurants = await response.json();
restaurantList.innerHTML = "";
nameSelect.innerHTML = "";
for (let i = 0; i < restaurants.length; i += 1) {
// 料理店の一覧を生成する部分
const li = document.createElement("li");
const name = document.createElement("h3");
const averageRating = document.createElement("p");
name.textContent = restaurants[i].name;
averageRating.textContent = `平均評価: ${restaurants[i].averageRating}`;
li.appendChild(name);
li.appendChild(averageRating);
restaurantList.appendChild(li);
// 評価する料理店の選択肢を生成する部分
const option = document.createElement("option");
option.value = i;
option.textContent = restaurants[i].name;
nameSelect.appendChild(option);
}
}
}, 1000);
コードの全体は以下を参照してください。