LoginSignup
1
1

More than 3 years have passed since last update.

DBから取り出したINT型フィールドを、星の数として表示する機能を実装する

Last updated at Posted at 2020-06-27

はじめに

AmazonなどのECサイトで、商品に対して星をつけて商品の評価をしているのを、
見たことありませんか?

「この商品は5つ星!これは3つ星!」のような。
アラビア数字で「これは何点」と表記されているよりも、すごくすごくわかりやすいですよね。

image.png

背景

筆者はWebフレームワークの勉強の課題として、
「読んだ技術書を評価してリストアップする」Webアプリケーションを製作中なのですが、
データベースに登録した評価カラムの数字を取り出して、その内容を星の個数として反映することを目指しました。

image.png

注意

  • 問題解決からしばらく経ってからの投稿なので、データベースの中身などに矛盾が発生しています。
    (例えば、対応する技術書の評価の数がスクリーンショットごとに異なるとか。)

  • 上の例のような、星3.5個というような小数は想定していません。
     あくまで星1, 2, 3, 4, 5個としての実装です。

開発環境

  • Node.js 12.16.3
  • Express 4.17.1
  • MySQL 8.0.19

実装したいもの

  • 星の数は常に5つ表示する
  • 評価数に応じて星の色をオレンジにすることで、評価点を確認できるようにする
  • 評価数に満たない部分は灰色の星として表示する
  • これらによって、「評価点の最大値がいくらか」「この本の評価点がいくつか」の可読性を一気に向上させる

解決方法

まずヴァニラなHTML・CSSを用意する

まず、星を表示するソースコードを用意する必要があります。

こちらを参考にしました。

改変したところ:uncheckedというクラスも用意した(文字色をgreyに変更する)

ソースコード


<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">

<span class="fa fa-star checked"></span>
<span class="fa fa-star checked"></span>
<span class="fa fa-star checked"></span>
<span class="fa fa-star unchecked"></span>
<span class="fa fa-star unchecked"></span>



.checked {
    color: orange;
}
.unchecked {
    color: grey;
}

表示結果

image.png

実装してみる

データベースの中身

このテーブルの"good"というカラムが評価(星の数)に対応します。

image.png

実装前のソースコードとスクリーンショット

app.js

app.get("/", (req, res) => {
  const sql = "select * from book";
  connection.query(sql, function (err, result, fields) {
    if (err) throw err;
    res.render("index", { book: result });
  });
});

inex.ejs

      <table>
        <tr>
          <th>タイトル</th>
          <th>著者</th>
          <th>出版社</th>
          <th>評価</th>
          <th>更新</th>
          <th>削除</th>
        </tr>
        <% book.forEach(function (value) { %>
        <tr>
          <td class="title"><%= value.title %></td>
          <td><%= value.author %></td>
          <td><%= value.publisher %></td>
          <td><%= value.good %></td>
          <td><a href="/edit/<%= value.title %>">更新</a></td>
          <td>
            <a
              href="/delete/<%= value.title %>"
              onClick="disp('<%= value.title %>'); return false;"
              >削除</a
            >
          </td>
        </tr>
        <% }); %>
      </table>

image.png

実装後のソースコードとスクリーンショット(そして補足コメント)

app.js

const maxStar = 5;

app.get("/", (req, res) => {
  const sql = "select * from book";
  connection.query(sql, function (err, result, fields) {
    if (err) throw err;
    books = [];
    for (book of result) {
      book.colored = book.good;  // 評価の数(オレンジ色の星の数)
      book.uncolored = maxStar - book.good;  // 灰色の星の数
      books.push(book);
    }
    res.render("index", { book: books }); 
  });
});
index.ejs

      <table>
        <tr>
          <th>タイトル</th>
          <th>著者</th>
          <th>出版社</th>
          <th>評価</th>
          <th>更新</th>
          <th>削除</th>
        </tr>
        <% book.forEach(function (value) { %>
        <tr>
          <td class="title"><%= value.title %></td>
          <td><%= value.author %></td>
          <td><%= value.publisher %></td>
          <td>
            <% for (let i = 0; i < value.colored; i++){ %>
            <span class="fa fa-star checked"></span>
            <% } %> <% for (let i = 0; i < value.uncolored; i++){ %>
            <span class="fa fa-star unchecked"></span>
            <% } %>
          </td>
          <td><a href="/edit/<%= value.title %>">更新</a></td>
          <td>
            <a
              href="/delete/<%= value.title %>"
              onClick="disp('<%= value.title %>'); return false;"
              >削除</a
            >
          </td>
        </tr>
        <% }); %>
      </table>

image.png

app.jsについて

実装前では「評価の数」だけあればよかったのですが、
今回は「オレンジ色に染まった星の数」「色がついていない(ように見える灰色の)星の数」という2つの変数が必要になります。
データベースからレコードを取り出したあと、
評価数の最大値(5)から、goodカラムの数を引くことで、灰色の星の数を取得し、
それらをまとめて初期化した配列 books に挿入、index.ejsへレンダリングすることで解決を図っています。

index.ejsについて

ejsファイルは通常HTMLで用いるJavaScriptだけでなく、
app.jsから渡されたデータを利用したJavaScriptを埋め込むことができます。

星の数について使った部分は以下です。
colored変数に格納された数だけforループしオレンジ色の星を表示、
uncolored変数に格納された数だけforループし、灰色の星を表示させます。

            <% for (let i = 0; i < value.colored; i++){ %>
            <span class="fa fa-star checked"></span>
            <% } %> <% for (let i = 0; i < value.uncolored; i++){ %>
            <span class="fa fa-star unchecked"></span>
            <% } %>
1
1
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
1
1