前回はこちら↓
お題
13で作ったモーダル内にinput (typeはnumber)をおいて、クリックした際にinput(type number)のvalueを取得して、リクエストできるようにしてください。fetchを直接ラップしている関数の引数にその値を渡してください
最初にプルリクエストしたコード
number用のinputをモーダルの中に作ります。
今回は、取得したinputの値を他の引数に渡す部分と、inputの入力エラーが発生した時の表示などの部分で、かなり悩んだ課題です。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<link rel="stylesheet" href="reset.css" type="text/css" />
<link rel="stylesheet" href="style.css" type="text/css" />
<script src="script.js" defer></script>
<title>JavaScript課題14 モーダルウィンドウの表示</title>
</head>
<body>
<ul id="js-list" class="list"></ul>
<button type="button" id="js-open-btn" class="btn open-btn">Click</button>
<div id="js-modal" class="modal">
<div class="modal-content">
<div class="close-btn" id="js-close-btn">
<img src="img/xmark-solid.svg" alt="クローズボタン">
</div>
<input type="number" id="js-input-number" value="" placeholder="100">
<button type="button" id="js-request-btn" class="btn">Request</button>
</div>
</div>
</body>
</html>
const showLoadingImg = () => {
const div = document.createElement('div');
const loadingImg = document.createElement('img');
div.id = "js-loading";
loadingImg.src = "img/loading-circle.gif";
loadingImg.alt = "ローディング画像";
document.body.insertAdjacentElement('afterbegin',div).appendChild(loadingImg);
}
const removeLoadingImg = () => {
document.getElementById('js-loading').remove();
}
const renderList = (result) => {
const fragment = document.createDocumentFragment();
for(const list of result){
const li = document.createElement('li');
const a = document.createElement('a');
const img = document.createElement('img');
li.className = "list-item";
a.href = `/${list.a}`;
a.textContent = list.text;
img.src = list.img;
img.alt = list.alt;
fragment.appendChild(li).appendChild(a).insertAdjacentElement('afterbegin',img);
}
document.getElementById('js-list').appendChild(fragment);
}
const fetchdata = async () => {
try{
const endpoint = "https://api.json-generator.com/templates/szdgGQcOLXuk/data?access_token=hu4bc7qh9znx2m8f53mn4mz2hryvdntkavwbw8j0";
const response = await fetch(endpoint);
if(!response.ok){
console.error(`${response.status}:${response.statusText}`)
}
const json = await response.json();
const data = await json.data;
return data;
}catch(error){
console.error(error);
}
}
const init = async (number) => {
showLoadingImg();
try{
console.log(number);
const result = await fetchdata();
if(!result){
return
}
renderList(result);
}catch(error){
document.getElementById('js-list').textContent = error;
console.error(error);
}finally{
removeLoadingImg();
}
}
const getInputNumber = () => {
const inputNumber = document.getElementById('js-input-number');
return inputNumber.value;
}
const modal = document.getElementById('js-modal');
const openBtn = document.getElementById('js-open-btn');
const closeBtn = document.getElementById('js-close-btn');
const requestBtn = document.getElementById('js-request-btn');
const closeModal = () => modal.classList.remove('is-show');
const openModal = () => modal.classList.add('is-show');
const hideOpenBtn = () => openBtn.classList.add('is-hide');
const showOpenBtn = () => openBtn.classList.remove('is-hide');
openBtn.addEventListener('click',() => {
openModal();
hideOpenBtn();
}, false);
closeBtn.addEventListener('click',() => {
closeModal();
showOpenBtn();
}, false);
requestBtn.addEventListener('click',() => {
const number = getInputNumber();
if(!number){
alert('数字を入力してください');
return;
}
init(number);
closeModal();
}, false);
レビュー
今回は、senさん、もなかさんにレビューして頂きました!ありがとうございます。
下記のnumberの値を渡す部分がかなり不安でしたが、あっているとのことでホッと一安心。
requestBtn.addEventListener('click',() => {
const number = getInputNumber();
if(!number){
alert('数字を入力してください');
return;
}
init(number);
closeModal();
}, false);
const div = document.createElement(‘div’);の部分は、何かわかりやすい変数名にした方が良いとのことで、const loadingPlace = document.createElement(‘div’);に直しました。
const showLoadingImg = () => {
const div = document.createElement('div');
const loadingImg = document.createElement('img');
div.id = "js-loading";
loadingImg.src = "img/loading-circle.gif";
loadingImg.alt = "ローディング画像";
document.body.insertAdjacentElement('afterbegin',div).appendChild(loadingImg);
}
const showLoadingImg = () => {
const loadingPlace = document.createElement('div');
const loadingImg = document.createElement('img');
loadingPlace.id = "js-loading";
loadingImg.src = "img/loading-circle.gif";
loadingImg.alt = "ローディング画像";
document.body.insertAdjacentElement('afterbegin',loadingPlace).appendChild(loadingImg);
}
今回、アロー関数を使って実装をしたのですが、単純に戻り値をかえすだけのコードであれば、もっと短くできることも教えてもらいました。
const getInputNumber = () => {
const inputNumber = document.getElementById('js-input-number');
return inputNumber.value;
}
3行が1行に!すごいです。returnを書かなくていいなんて感動です。
const getInputNumberValue = () => document.getElementById("js-input-number").value;
最終的なコード
下記のコードでApprove頂きました。大幅な修正はなく、よかった!
<html lang="ja">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<link rel="stylesheet" href="reset.css" type="text/css" />
<link rel="stylesheet" href="style.css" type="text/css" />
<script src="script.js" defer></script>
<title>JavaScript課題14 モーダルウィンドウの表示</title>
</head>
<body>
<ul id="js-list" class="list"></ul>
<button type="button" id="js-open-btn" class="btn open-btn">Click</button>
<div id="js-modal" class="modal">
<div class="modal-content">
<div class="close-btn" id="js-close-btn">
<img src="img/xmark-solid.svg" alt="クローズボタン">
</div>
<input type="number" id="js-input-number" value="" placeholder="100">
<button type="button" id="js-request-btn" class="btn">Request</button>
</div>
</div>
</body>
</html>
const showLoadingImg = () => {
const loadingPlace = document.createElement('div');
const loadingImg = document.createElement('img');
loadingPlace.id = "js-loading";
loadingImg.src = "img/loading-circle.gif";
loadingImg.alt = "ローディング画像";
document.body.insertAdjacentElement('afterbegin',loadingPlace).appendChild(loadingImg);
}
const removeLoadingImg = () => document.getElementById('js-loading').remove();
const renderList = (result) => {
const fragment = document.createDocumentFragment();
for(const list of result){
const li = document.createElement('li');
const a = document.createElement('a');
const img = document.createElement('img');
li.className = "list-item";
a.href = `/${list.a}`;
a.textContent = list.text;
img.src = list.img;
img.alt = list.alt;
fragment.appendChild(li).appendChild(a).insertAdjacentElement('afterbegin',img);
}
document.getElementById('js-list').appendChild(fragment);
}
const fetchData = async () => {
try{
const endpoint = "https://api.json-generator.com/templates/szdgGQcOLXuk/data?access_token=hu4bc7qh9znx2m8f53mn4mz2hryvdntkavwbw8j0";
const response = await fetch(endpoint);
if(!response.ok){
console.error(`${response.status}:${response.statusText}`)
}
const json = await response.json();
const data = await json.data;
return data;
}catch(error){
console.error(error);
}
}
const init = async (number) => {
showLoadingImg();
try{
console.log(number);
const result = await fetchData();
if(!result){
return;
}
renderList(result);
}catch(error){
document.getElementById('js-list').textContent = error;
console.error(error);
}finally{
removeLoadingImg();
}
}
const getInputNumber = () => document.getElementById('js-input-number').value;
const modal = document.getElementById('js-modal');
const openBtn = document.getElementById('js-open-btn');
const closeBtn = document.getElementById('js-close-btn');
const requestBtn = document.getElementById('js-request-btn');
const closeModal = () => modal.classList.remove('is-show');
const openModal = () => modal.classList.add('is-show');
const hideOpenBtn = () => openBtn.classList.add('is-hide');
const showOpenBtn = () => openBtn.classList.remove('is-hide');
openBtn.addEventListener('click',() => {
openModal();
hideOpenBtn();
}, false);
closeBtn.addEventListener('click',() => {
closeModal();
showOpenBtn();
}, false);
requestBtn.addEventListener('click',() => {
const number = getInputNumber();
if(!number){
alert('数字を入力してください');
return;
}
init(number);
closeModal();
}, false);
今回学んだこと
- アロー関数の書き方
- inputの値の取得方法
次回も頑張ります!
私が所属しているフロントエンドエンジニアを目指す方のための塾 「もりけん塾」の森田賢二先生のTwitterはこちら!
【募集】フロントエンド、とりわけJavaScriptを教えてもらいたい塾生を募集しています。条件はありますが、お金は頂きません。詳しくはDMください#JavaScript教えてもらいたい方#駆け出しのエンジニアと繋がりたい
— フロントエンドエンジニア (@terrace_tech) April 18, 2020
わたしについて👉https://t.co/FETVmMT5AY
先生のブログ「武骨日記」はこちら!