Axios 簡単なデモページの作成2[JavaScript]

APIから情報を取得する方法を学んだので、
その知識と今まで学んできたことを総合して簡単なデモページを作成していこうと思います。

デモページの内容：

TV番組の検索を行えるアプリを作成していきます。

検索したTV番組に応じた画像を、ループを回して表示する一覧画面を作成していきます。

こちらでは、作成した内容を要約しながら、作成手順や具体的に使用した関数やロジックの内容をまとめていけたらと思います。

目次：
- [デモページ詳細](#デモページ詳細)
- [HTMLファイル](#htmlファイル)
- [ロジックの説明「JavaScriptファイル」](#ロジックの説明javascriptファイル)


## デモページ詳細

今回は、TVMAZEというTV番組のAPIから情報を取得していきたいと思います。

<img src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3679750/5270007d-ebe3-dc62-35a4-c7f6f48a9c3b.png width = 60%>


まずは、取得をするにあたって、APIのデータがどのようになっているのかを確認してみます。
search ExampleをPOSTMANに貼り付けて、データの中身を確認してみます。

<img src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3679750/7c2f6e4e-0317-c804-20b6-fed6c112a10f.png width = 60%>

<img src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3679750/790c596a-6208-dc3d-1120-71c119f3122a.png width = 60%>

showというキーがあり、その中を見ていくとimageとあり、その中にmediumとoriginalがあります。
この画像の情報（medium）を使用し、検索をしたものに対して、もらった画像の情報を自分のページに出力するシンプルなデモページを作成していいます。

## HTMLファイル

HTMLはシンプルな設計です。

1. axiosを使用するので、headにCDNで接続しています。
2. JavaScriptファイルと接続するため、末尾にscriptタグでapp.jsファイルと接続しています。
3. h1でタイトルを表示
4. 検索用のformを作成し、inputで番組名を入力できるようにし、placeholderを設定しています。
また、formを使用できるようにidを設定します。inputも後で使用するためにnameを設定しておきます。
5. buttonで入力した番組名を送信し、その内容に応じた画像を出力するようにします。    

```html
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
</head>
<body>
    <h1>テレビ番組の検索</h1>
    <form id="searchForm">
        <input type="text" placeholder="番組名" name="query">
        <button>検索</button>
    </form>

    <script src="app.js"></script>
```

<img src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3679750/55997200-dea2-5d19-35a7-1f03bdaebff1.png width = 60%>

## ロジックの説明「JavaScriptファイル」

#### Formのデフォルトの挙動を停止

まずは、JavaScriptでformを取得し、デフォルトの挙動を停止させます。

```js
const form = document.querySelector('#searchForm');
form.addEventListener('submit',function(e) {
    e.preventDefault();
    console.log('submit!');
});
```
デフォルトの挙動が停止し、ログが出力できていることを確認します。

<img src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3679750/fcf1b824-9e61-94cb-1f51-93c686ddeccf.png width = 60%>

#### Formの中身を取得する

Formの中身を取得するにはどうすれば良いでしょうか？

console.dir(Form)でFormの中身を確認してみます。

<img src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3679750/e9285c56-aa66-5db5-b8ad-2ca7ac61c141.png width = 60%>

Formの中身を取得するには、
form.elements.query.valueで取得することができます。


<img src  = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3679750/17696a4e-ff3d-cde7-c0e2-1c94fdec46ae.png width = 60%>

この取得した値を使って検索をかけます。
また、後ほどinput内のリセットも行うため、一旦変数に保存しておこうと思います。

```js
const searchTermInput = form.elements.query;
```

#### APIに検索をかける

続いて、axiosを使用し、APIに検索をかけたいと思います。
また、検索をかける値は、先ほど作成したsearchTermInputを使用するため、テンプレートリテラルを使用します。
取得した値をresという変数に入れ、res.dataとして値が取得できているのかを確認してみます。

axios.getはPromiseなので、async、awaitをかけるのをお忘れなく。

```js
const form = document.querySelector('#searchForm');
form.addEventListener('submit',async function(e) {
    e.preventDefault();
    const searchTermInput = form.elements.query;
    const res = await axios.get(`https://api.tvmaze.com/search/shows?q=${searchTermInput.value}`)
    console.log(res.data);
});
```

無事に取得できています。

<img src  =https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3679750/7c703200-f1ee-4967-b8da-dea2e2f10926.png width = 60%>

更に、ログの値を変更することで、意図した画像のURLを取得することができます。
```js
console.log(res.data[0].show.image.medium);
```

<img src =https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3679750/c3df888b-963a-234c-8768-cfcb2e50906a.png width = 60%>

#### 画像の表示

続いてこの取得した画像を一覧画面に出力してみたいと思います。

```js
    const img = document.createElement('IMG');
    img.src = res.data[0].show.image.medium;
    document.body.append(img);
```
imgタグを作成、そのimgのsrcに検索した結果を挿入します。
bodyにappendする形で一旦画像を出力してみます。

pokemonと検索することにより、pokemonに対応したTV番組の画像が出力されました。

<img src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3679750/77a94b79-3573-20c0-b7b4-bf760f5525d9.png width = 60%>

## 検索した画像を複数表示

ループする部分は別の関数として出力してみます。

makeImages関数として、res.dataを受け取るようにします。

```js
makeImages(res.data)
});
```
makeImages関数の内部ではfor..ofループを回します。
for..ofループでは、受け取ったdata（配列）が、resultsに渡され、
resultsは一つ一つをresultに渡されて、それをimgのsrcに渡して出力させます。

```js
const makeImages = (results) => {
    for(let result of results) {
        const img = document.createElement('IMG');
        img.src = result.show.image.medium;
        document.body.append(img);
    }
}
```

無事に、APIに検索をかけた結果をループで回して画像を出力することができました。

<img src = https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3679750/55f8827c-72ee-7a5f-44b2-20cb445e6980.png width = 60%>

#### 検索結果をから文字にする

```js
searchTermInput.value = ''
```

用意していた変数のvalueを検索終了後に空文字に変更します。

#### axiosのリファクタ「JavaScriptファイル」

直にクエリストリングを指定する場合、URLを作る場所がごちゃごちゃしてしまうので、
axiosの違う指定方法を使用し、クエリストリングの設定を行なっていきます。

```js
const config = {
        params: {
            q: searchTermInput.value
        }
    }
    const res = await axios.get('https://api.tvmaze.com/search/shows', config)
```

1. URLをそのままシングルクォートで囲います。
2. 変化するクエリストリングの部分を、configというオブジェクトを別で用意します。
3. configの中には、paramsというキーで、そこにオブジェクトを入れることができます。
このparamsに設定したキーと値がそのままクエリストリングのキーと値になります。 

#### 検索結果をクリアする機能

検索結果をクリアする関数を作成します。

```js
const clearImages = () => {
    const images = document.querySelectorAll('img');
    images.forEach(img => img.remove());
}
```
clearImages関数は、新しい検索結果を表示する前に、以前の画像を全て削除します。

作成したclearImages関数をmakeImagesの前に挿入します。
```js
    clearImages();
    makeImages(res.data)
    searchTermInput.value = ''
});
```