機能拡張v.1

前章までは、見た目だけで機能はない。 本章では、簡単な検索機能を実装する。

サンプルコードは、こちら

team_search/serve.js

const express = require('express')
const app = express()
app.set("view engine", "ejs")
const port = process.env.PORT || 6000;

app.get('/search-box', (req, res) => {
  const defualtQuery = {k: ''}
  const query = Object.assign(defualtQuery, req.query);
  res.render('./search-box.ejs', query);
})

app.listen(port, () => {
  console.log(`Team Search app listening at http://localhost:${port}`)
})

team_search/views/search-box.ejs

<style>
    .team-search-box-button {
        border: none;
        background-color: inherit;
    }
    .team-search-box-input {
        width: 50%;
    }
</style>
<form method="GET" action="./">
    <input name="k" value="<%= k %>" placeholder="Please enter keywords ..." class="team-search-box-input"></input><button class="team-search-box-button" type="submit">🔍</button>
</form>

formを使い、buttontype="submit"と書くことで、サーバーへ検索キーワードを送信するようにする。

組成

team_composite/serve.js

const express = require('express');
const fetch = require('node-fetch');
const app = express();
app.set("view engine", "ejs");

const port = process.env.PORT || 2000;
const inspireHost = process.env.INSPIRE_HOST || 'localhost:4000';
const productHost = process.env.PRODUCT_HOST || 'localhost:5000';
const searchHost = process.env.SEARCH_HOST || 'localhost:6000';

const items = ['apple', 'banana', 'grapes', 'mango', 'orange'];
const filterItems = (arr, query) => {
  return arr.filter(el => el.toLowerCase().indexOf(query.toLowerCase()) !== -1)
};

app.get('/',  async (req, res) => {
  queryParams = req.query;
  keyword = queryParams['k'];
  let localItems = items;
  if (keyword !== undefined) {
    localItems = filterItems(items, keyword);
  }
  urlQueryParams = Object.keys(queryParams).map(key => key + '=' + queryParams[key]).join('&');
  const inspireList = await (await fetch(`http://${inspireHost}/inspire-list?i=${localItems.join(',')}`)).text();
  const inspireLabel = await (await fetch(`http://${inspireHost}/inspire-label`)).text();
  const productList = await (await fetch(`http://${productHost}/product-list?i=${localItems.join(',')}`)).text();
  const searchBox = await (await fetch(`http://${searchHost}/search-box?${urlQueryParams}`)).text();
  res.render("./index.ejs", {
    inspireList: inspireList,
    inspireLabel: inspireLabel,
    productList: productList,
    searchBox: searchBox
  });
});

app.listen(port, () => {
  console.log(`Team Composite app listening at http://localhost:${port}`)
});

検索キーワードをクエリパラメータkに格納される。 kから商品(items)をフィルタリングし、その結果をproductListinspireListへURLのクエリパラメータ(i)として渡す。

フラグメント - team-product-list -

team_product/serve.js

const express = require('express')
const app = express()
app.set("view engine", "ejs")
const port = process.env.PORT || 5000;

app.get('/product-list', (req, res) => {
  const defualtQuery = {items: []}
  let query = defualtQuery;
  query['items'] = req.query['i'].split(',').filter((e) => e !== '');
  res.render('./product-list.ejs', query)
})

app.listen(port, () => {
  console.log(`Team Product app listening at http://localhost:${port}`)
})

URLのクエリパラメータiより、商品のリストを表示する。

team_product/views/product-list.ejs

<style>
    .team-product-item {
        border: medium solid;
        display: inline-block;
        text-align: center;
        padding: 20px 0;
        width: 100%;
        margin: 10px 0;
    }
</style>
<% for (let item of items) { %>
    <%- include("./product-item.ejs", {item: item}) %>
<% } %>

フラグメント - team-inspire-list -

team_inspire/serve.js

const express = require('express')
const app = express()
app.set("view engine", "ejs")
const port = process.env.PORT || 4000;

const recommendItems = {
  apple: ['apple pie'], 
  banana: ['banana juice'], 
  grapes: ['grape mousse'], 
  mango: ['mango ice'], 
  orange: ['orange cake']
}

app.get('/inspire-list', (req, res) => {
  const defualtQuery = {items: []}
  let query = defualtQuery;
  const productItems = req.query['i'].split(',').filter((e) => e !== '');
  const localRecommendItems = productItems.map((item) => recommendItems[item]).flat();
  query['items'] = localRecommendItems;
  res.render('./inspire-list.ejs', query);
})

app.get('/inspire-label', (req, res) => {
  res.render('./inspire-label.ejs');
})

app.listen(port, () => {
  console.log(`Team Inspire app listening at http://localhost:${port}`)
})

URLのクエリパラメータiより、お勧めする商品を探索し、それを表示する。

team_inspire/views/inspire-list.ejs

<style>
  .team-inspire-item {
    border: medium solid;
    display: block;
    text-align: center;
    padding: 20px 0;
    border-radius: 50%;
    margin: 10px 0;
  }
</style>
<% for (let item of items) { %>
    <%- include("./inspire-item.ejs", {item: item}) %>
<% } %>

結果

その結果、次のような画面が表示される。

04_function_1_server_side_composition_tutorial
Fig. 114 04_function_1_server_side_composition_tutorial

results matching ""

    No results matching ""