0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【JavaScript】APIからJSONを取得して静的ページにお知らせを追加してみる

Posted at

JavaScriptを使って、APIからJSONを取得して、整形&リストアップして表示してみたいと思います。

フロントエンドは、静的ページに埋め込んだプレーンなJavaScriptになります。
バックエンドには、カンタンにAPI公開できる拙作のWebサービス「パケットベース」を利用しました。

パケットベース - Packetsbase
パケットベース

組織間でデータを送受信でき、受け取ったデータをノーコードでAPI公開できるサービスです。
自分あてにデータを送れば、自分用にAPIサーバーを立ち上げることもできます。

フロントエンド

今回、簡単にプレーンなJavaScriptでコードを書いてみます。
ReactもVueも使わないというのは久しぶりで、ある意味新鮮です。

設計

設計としては、

  1. ベースとなるHTMLにエレメントを用意しておく
  2. テンプレートとなるHTMLを用意する
  3. APIからJSONを取得する
  4. テンプレートにJSONの内容を当てはめてHTMLを作ってページに入れる
  5. リストアイテムをクリックすると詳細を表示する

という感じになります。

コード

コードはこんな感じになりました。

1.ベースとなるHTMLにエレメントを用意しておく

<body onload="init()">
(略)
  <div id="whatsNew"></div>
  <div id="whatsNewDetail" style="display: none;"></div>

bodyタグにonloadとしてinit()関数を入れておき、ページのコンテンツをすべて読み込み終わってからリストを表示するようにします。
また、リスト表示用のエレメントと詳細表示用のエレメントを用意し、詳細表示の方は display: none; にしておきます。

2.テンプレートとなるHTMLを用意する

const list = `
  <hr>
  <h2>お知らせ</h2>
  <ul>
    {listItems}
  </ul>
  <hr>
`

const listItem = `
  <li>
    {date}
    &nbsp;:&nbsp;
    <a href="" onclick="return handleWhatsNewDetail({id})">
      {title}
    </a>
  </li>
`

const detail = `
  <div>
    <h3>{title}</h3>
    <button onclick="handleWhatsNewClose()">✕</button>
    <div>
      <p>{date}</p>
      <p>{content}</p>
    </div>
  </div>
`

リストの親要素とリストアイテム、詳細表示用のエレメントを用意します。
HTMLを変数に入れていて、プレースホルダーには波括弧を使っています。

3.APIからJSONを取得する

let articles = []

const init = async () => {
  const apiUrl = "https://packetsbase.net/api/p/packetsbase_whatsnew"
  const response = await fetch(apiUrl, {
    method: 'POST',
    body: {
      number: 5,
      order: 'desc',
      page: 1,
      sort: 'createdAt',
    },
  })
  const data = await response.json()
  articles = data.results
}

1.で呼び出すようにした init() 関数を用意します。
APIにアクセスしてJSONを取得する部分は、ビルトインのfetchを使っています。
「パケットベース」で公開しているAPIエンドポイントに、POSTでパラメーターを渡してアクセスすると、JSONを取得することができます。

4.テンプレートにJSONの内容を当てはめてHTMLを作ってページに入れる

const init = async () => {

  const listItems = articles.map(
    (item) => listItem.replace('{id}', item.id)
      .replace('{date}', item.date)
      .replace('{title}', item.title),
  )

  const html = list.replace('{listItems}', listItems.join(''))
  document.getElementById('whatsNew').innerHTML = html
}

3.で作った init() 関数の後ろに追加しておきます。
テンプレートHTML中のプレースホルダーを、取得したJSONの値で置換し、1.で用意したエレメントに入れます。

5.リストアイテムをクリックすると詳細を表示する

const handleWhatsNewClose = () => {
  document.getElementById('whatsNewDetail').style.display = 'none'
}

const handleWhatsNewDetail = (id) => {
  const article = articles.find((item) => item.id === id)
  const html = detail.replace('{title}', article.title)
    .replace('{date}', article.date)
    .replace('{content}', article.content)
  const element = document.getElementById('whatsNewDetail')
  element.style.display = 'block'
  element.style.position = 'fixed'
  element.style.top = '0'
  element.style.left = '0'
  element.style.width = '100vw'
  element.style.height = '100vh'
  element.style.backgroundColor = 'rgba(0, 0, 0, 0.4)'
  element.style.zIndex = '1000'
  element.onclick = handleWhatsNewClose
  element.innerHTML = html
  return false
}

リストアイテムをクリックして詳細表示ダイアログを表示したり閉じたりする処理を追加します。

詳細表示用のエレメントに生成したHTMLを入れて display プロパティを変更して表示させます。

ここでは親となるエレメントを画面全面に表示して画面をマスクし、詳細表示ダイアログを前面に出すようにしています。
また、親エレメントのどこかをクリックするとダイアログを閉じるようにしています。

バックエンド

今回、バックエンドは「パケットベース」で用意しました。
「パケットベース」の簡単な使い方は以前ご紹介していますのでこちらをご覧ください。

「パケットベース」では、自分あてにデータを送ってバスケットに入れておくことでAPI公開できるようになっているので、データを作成します。

パケットを送信

データを作成したら、公開APIを作成してデータを取得できるようにします。

公開API一覧

完成

スタイルとかいろいろ整えると、こんな感じになります。

リスト表示

詳細表示

さいごに

パケットベース - Packetsbase

制限はありますが基本無料で使えるので、よかったら使ってみてくださいね!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?