普通文組 2.5

「Express Handlebars 取得父層變數內容」相關筆記

問題描述

  • 情境:在 express-handlebars 中使用原生的each搭配 handlebars-helpers 的is進行條件判斷,進而渲染出一組<select>
    • <select>中的每一個<option>都是一種餐廳類型(舉例:日本料理、酒吧、美式餐廳等)
    • (由app.js傳遞給edit.handlebars的變數)categories為餐廳類型的陣列資料,restaurant為物件變數,可透過restaurant.category來取得該餐廳的餐廳類型
    • each迴圈中this的值與restaurant.category一致時,pre-selected 該<option> select欄位應預設選擇該餐廳的類型
  • 問題:檢查最終的 DOM 內容,發現並沒有渲染出應該要預先被選擇的<option>
  • 行為不如預期的原始碼:
    // app.js端
    app.get("/restaurants/:id/edit", (req, res) => {
      const id = Number(req.params.id);
      const targetRestaurant = restaurantList.results.find(
        (restaurant) => restaurant.id === id,
      );
      const categories = [];
      restaurantList.results.forEach((restaurant) => {
        if (!categories.includes(restaurant.category)) {
          categories.push(restaurant.category);
        }
      });
      res.render("edit", { restaurant: targetRestaurant, categories });
    });
    <!-- handlebars端 -->
    {{#each categories}} {{#is this restaurant.category)}}
    <option value="{{this}}" selected>{{this}}</option>
    {{else}}
    <option value="{{this}}">{{this}}</option>
    {{/is}} {{/each}}

環境

express-handlebars: 5.3.2
handlebars-helpers: 0.10.0

解決方式

將 handlebars 端的內容修改如下(restaurant.category加上../):

<!-- handlebars端 -->
{{#each categories}} {{#is this ../restaurant.category)}}
<option value="{{this}}" selected>{{this}}</option>
{{else}}
<option value="{{this}}">{{this}}</option>
{{/is}} {{/each}}

參考 Handlebars 官方文件的說明:

Some helpers like #with and #each allow you to dive into nested objects. When you include ../ segments in your path, Handlebars will change back into the parent context.

在巢狀結構中,使用../來取得上一層變數的內容

參考文件