AIプログラミングアシスタントツール「GitHub Copilot Chat」を使って、JavaScriptによるWebアプリケーションの開発の仕方を学ぶ本連載。前回は、GitHub Copilot Chatを使ってOpenWeather APIから天気データを取得し、コンソールに表示するところまで進めた。

今回はその続きとして、取得したデータを実際の画面に表示し、使いやすいUIと機能拡張を加えていこう。→連載「GitHub Copilot ChatではじめるJavaScript開発」のこれまでの回はこちらを参照

取得したデータを画面に反映させる

まずは、OpenWeather APIから取得した天気情報(気温・天気説明・アイコン)を画面に表示してみる。Copilot Chatに次のように依頼してみよう。

APIから取得した天気データを画面に表示したいです。
都市名、気温、天気説明、アイコンを表示するコードを追加してください

筆者の環境では、script.jsの修正案として次のコードを提案してくれた。

// OpenWeather APIキー(ダミー)
const API_KEY = "YOUR_API_KEY_HERE";

// 検索ボタンのクリックイベントを設定
document.getElementById('search-btn').addEventListener('click', () => {
    // 入力された都市名を取得
    const city = document.getElementById('city-input').value.trim();
    if (!city) return; // 空欄なら何もしない

    // OpenWeather APIのURLを作成
    const url = `https://api.openweathermap.org/data/2.5/weather?q=${encodeURIComponent(city)}&appid=${API_KEY}&lang=ja&units=metric`;

    // 取得中表示(簡易)
    const infoEl = document.getElementById('weather-info');
    infoEl.textContent = '読み込み中...';

    // fetchでAPIリクエストを送信
    fetch(url)
        .then(response => {
            // ステータスチェック:404などはここで検出
            if (!response.ok) {
                throw new Error(`HTTP error! status: ${response.status}`);
            }
            // レスポンスをJSONに変換
            return response.json();
        })
        .then(data => {
            // 取得した天気データをコンソールに表示
            console.log(data);

            // 必要なフィールドを取り出す
            const name = data.name || '';
            const country = data.sys && data.sys.country ? data.sys.country : '';
            const temp = data.main && typeof data.main.temp === 'number' ? Math.round(data.main.temp) : '―';
            const description = data.weather && data.weather[0] && data.weather[0].description ? data.weather[0].description : '';
            const iconCode = data.weather && data.weather[0] && data.weather[0].icon ? data.weather[0].icon : null;
            const iconUrl = iconCode ? `https://openweathermap.org/img/wn/${iconCode}@2x.png` : '';

            // 表示用HTMLを組み立てる
            infoEl.innerHTML = `
                <div class="weather-card">
                    <div class="weather-main">
                        <div class="weather-location">${name}${country ? ', ' + country : ''}</div>
                        <div class="weather-temp">${temp}°C</div>
                        <div class="weather-desc">${description}</div>
                    </div>
                    ${iconUrl ? `<div class="weather-icon"><img src="${iconUrl}" alt="${description}"></div>` : ''}
                </div>
            `;
        })
        .catch(error => {
            // エラー時は表示とコンソールにエラー内容を表示
            console.error('天気情報の取得に失敗しました:', error);
            infoEl.textContent = '天気情報の取得に失敗しました。都市名を確認してください。';
        });
})

また、チャット欄には次のような補足説明が表示された。

手順(簡潔):

1. fetchで取得したJSONから必要なフィールド(都市名、気温、天気説明、アイコン)を取り出す。
2. #weather-info 要素に適切なHTMLを組み立てて挿入する。
3. エラーや見つからない場合の表示を行う(response.okのチェックとキャッチ処理)。

変更ファイル(まとめ)
script.js

天気データを解析して画面に表示する処理を追加します。コンソール表示は残しつつ、都市名・気温・天気説明・アイコンを #weather-info に描画します

コードの変更を反映させたら、Webブラウザでindex.htmlを開いてみよう。都市名に「Tokyo」と入力して[検索]ボタンをクリックすると、次のように現在の東京の天気がアイコン付きで表示される。

  • 天気が気温やアイコン付きで表示できた

    天気が気温やアイコン付きで表示できた

なお、OpenWeather APIは日本語の都市名には対応していないので、都市名を「東京」とした場合には次のようにエラーメッセージが表示される。

  • エラーが発生した場合にはエラーメッセージが表示される

    エラーが発生した場合にはエラーメッセージが表示される

これは、チャットの説明の「3」に書かれているように、APIからエラーが返ってきた場合には、その旨の表示を行う処理を追加した効果である。

JSONデータの処理方法についてチャットに聞く

たとえAIが自動でコードを書いてくれたとしても、人間がその内容を理解することはきわめて重要である。コードの内容を理解していなければ、それが正しいかどうかを判断できないし、もし後から何か問題が発生したとしても、その原因の追求や修正が困難になってしまう。

そこで、コードの理解を助けるために、Copilo Chatに細かく質問してみよう。例えば、そのプログラムの核になるのはAPIから返ってきたJSONコードを処理箇所だ。そこで次のように、その処理部分について聞いてみる。

JSONデータを処理している部分について詳しく説明してください

するとCopilot Chatは、次のようにその手順をステップごとに解説してくれた。

手順(簡潔に段階分け):

1. HTTPレスポンスのチェック
    ・fetch の最初の then で response.ok を確認し、失敗(例: 404)の場合は throw して catch に渡す。

2. JSONへの変換
    ・response.json() を呼んでレスポンスボディをパースし、次の then に JSON オブジェクト(data)を渡す。

3. デバッグ出力
    ・取得した JSON 全体を console.log(data) で表示して構造を確認する。

4. 必要フィールドの抽出(安全に取り出す)
    ・都市名: data.name(存在しない場合は空文字にフォールバック)
    ・国コード: data.sys.country(存在しない場合は空文字)
    ・気温: data.main.temp を数値で丸めて表示(存在しない場合は '―')
    ・天気説明: data.weather[0].description(配列や要素の存在をチェック)
    ・アイコンコード: data.weather[0].icon(あれば openweathermap のアイコン URL を作成)
取り出し時は存在チェック(例: data.main && typeof data.main.temp === 'number')を行い、未定義アクセスで例外にならないようにしている。

5. 表示用HTMLの組み立てと挿入
    ・上で取り出した値をテンプレートリテラルで組み合わせ、infoEl.innerHTML に代入して画面に反映する。アイコンが無ければ画像タグを出さないよう条件レンダリングしている。

6. エラー処理
    ・fetch や JSON パース、あるいは response.ok のチェックで発生したエラーは catch に入り、console.error に出力し、画面にはエラーメッセージを表示する。

補足(改善案・注意点):

・optional chaining を使うとコードを簡潔にできる(例: const temp = data.main?.temp)。
・data.weather が空配列の場合のガードを入れる(length チェック)。
・APIキーやネットワークエラーと API 側エラー(ステータスコード)を区別してユーザーに伝えると親切。
・ユーザー入力のバリデーションやローディング/エラーUIを充実させると UX が向上する

この段階でまだ分からないことがあれば、さらに詳しく聞いてみるといいだろう。例えば、JSONデータから情報を取り出すのにどうやって分解するのかなど、より詳しく突っ込んで質問することで理解を深めることができる。

チャットでUIの調整を依頼する

次に、情報が見やすくなるようにデザインを整えよう。どのような見栄えにしたいかを考えて、Copilot ChatにCSSを修正してもらうように依頼すればよい。今回は、次のように指示してみた。

天気情報の表示部分をカード風にデザインしてください。
中央寄せで、背景は淡い青のグラデーションにしてください

Copilot Chatはstyle.cssを書き換えて、チャット欄に次の補足情報を表示した。

手順:

1. ページ全体の背景を淡い青のグラデーションに変更します。
2. 天気表示エリア(#weather-info)を中央寄せのカードコンテナに整えます。
3. カード内部(.weather-card)を横並びのフレックスにして、テキストとアイコンを見やすく配置します。
4. フォントサイズ・余白・シャドウでモダンな見た目に仕上げます

Webブラウザでindex.htmlをリロードして再び「Tokyo」を検索してみると、次のように天気の表示部分の見た目がカード風のデザインに書き換わったことが確認できる。ページの背景色も少し変わって、グラデーションが付いた。また、結果表示部分にマウスカーソルが乗ったときに、カードが少し浮き上がるようなアニメーション効果も追加されている。

  • 天気の表示欄がカード風になった

    天気の表示欄がカード風になった

style.cssの変更箇所は長いので一部だけ取り上げると、次のように.weather-mainや.weather-cardなどのクラスに関するスタイルが追加されている。

#weather-info:hover {
    transform: translateY(-4px);
    box-shadow: 0 12px 36px rgba(16,40,80,0.10);
}

.weather-card {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    gap: 12px;
}

.weather-main {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 6px;

実は、先程のscript.jsで結果表示のHTMLを組み立てている箇所をよく見ると、この段階で各要素にはすでにデザイン用のこれらのクラス指定が行われていることが分かる。

// 表示用HTMLを組み立てる
infoEl.innerHTML = `
    <div class="weather-card">
        <div class="weather-main">
            <div class="weather-location">${name}${country ? ', ' + country : ''}</div>
            <div class="weather-temp">${temp}°C</div>
            <div class="weather-desc">${description}</div>
        </div>
        ${iconUrl ? `<div class="weather-icon"><img src="${iconUrl}" alt="${description}"></div>` : ''}
    </div>
`

つまり、CopilotはJavaScriptを生成した時点でCSSのことも想定していたわけだ。