【Pug】Pugで編集されたファイルを元に、JQueryで値埋め込み

# 概要

[前回](https://qiita.com/myantyuWorld/items/8a223c7c6e917e822cee)”Pug”とは何なのか、簡単ではありますが、説明させていただきました。
今回は、Pugで記述されたテンプレートファイルを元に、JQueryの値埋め込み処理を記述する例を自分用にメモとして残します

# 前提

システム開発において、固定値で画面が作成される、なんてことはありえないです
jsのソースコードに、動的に値をDOMに埋め込んでいく実装を進めていくと思いますが、Pug記法を使用することはできない
（＝Pugは、あくまでHTMLのテンプレートエンジン）

# ステップ１
#### index.js
JQueryで値を動的にHTMLに対して設定する例として、まず思いつくのは
1. モック画面を開発者ツールなどで調べ、明細部のHTMLをコピー
2. それをjs部分に貼り付けて、テンプレートリテラルなどを使って、値を設定する

感じでしょうか。私のレベルはここでした。。。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587970/6c244346-3f2c-09eb-7c8b-e205c990ac6f.png)

```index.js
$(function() {
    //　APiリクエストなどして取得したデータ例
    var list = [
        {
            date:"2022/09/03",
            memo:"",
            name:"枝豆"
        },
        {
            date:"2022/09/03",
            memo:"hogehoge",
            name:"ビール"
        }
    ]

    //　元のHTMLを開発者ツールなどで、取得してくる
    list.forEach((elem, index) => {
        var dom = `
        <div class="activity-table-tr">
        <div class="activity-table-td-left">
          <div class="activity-table-td--date">${elem.date}</div>
          <div class="activity-table-td--name">${elem.name}</div>
        </div>
        <div class="activity-table-td-right">
          <div class="activity-table-td--memo">${elem.memo}</div>
        </div>
      </div>
        `
    $(".activity-table-body").append(dom)
    })
});

```

これで全然実装できます。
ただ、このやり方の問題点としては、
1. データの操作をしたいだけなのに、見た目の実装に深く依存している
1. UI変更（クラス名や、HTML要素の変更）が発生したとき、非常に困難な修正となる

っと、行った感じで、”力技”感は否めませんよね

# ステップ２

特徴
- jsファイルに、HTML要素(や、クラス名{見た目に影響するようなもの}の記述を極力行わない
- データ操作、に着目する観点で、データ属性を付与し、それを中心に検索・操作する
- Pugファイル＝テンプレート、の観点で、テンプレートを複製し、複製したDOMに対して操作する


#### Pugファイル（Before）


```index.pug
doctype html
html(lang="ja")
  head
    title タイトル
    meta(charset='utf-8')
    meta(http-equiv="X-UA-Compatible", content="IE=edge,chrome=1")
    meta(name="viewport", content="width=device-width, initial-scale=1")
    block link
      link(rel='stylesheet', href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css")
  body
  .container

    button.btn.  
        api request

    hr

    h1#heading タイトル
    hr
    .activity-table
        .activity-table-body 
            each item in list 
                .activity-table-tr
                    .activity-table-td-left
                        .activity-table-td--date=item.date
                        .activity-table-td--name=item.name
                    .activity-table-td-right
                        .activity-table-td--memo=item.memo
                hr
    block end_of_body 
        script(src="https://code.jquery.com/jquery-3.6.1.min.js") 
        script(src="./index.js") 
```


#### Pugファイル(After)

"data-js-text={XXXX}"に着目してみてください
データ操作用のデータ属性を付与しています

```index.pug
... 省略

    h1#heading タイトル
    hr
    .activity-table
        .activity-table-body 
            .activity-table-tr(data-js-each="table-list-items")
                .activity-table-td-left
                    .activity-table-td--date(data-js-text="date")
                    .activity-table-td--name(data-js-text="name")
                .activity-table-td-right
                    .activity-table-td--memo(data-js-text="memo")
            hr
    block end_of_body 
        script(src="https://code.jquery.com/jquery-3.6.1.min.js") 
        script(src="./index.js") 
```

#### index.js

いかがでしょうか。
HTML要素の記述は、極力なくせたと思います。

```index.js
$(function() {
    //　APiリクエストなどして取得したデータ例
    var list = [
        {
            date:"2022/09/03",
            memo:"",
            name:"枝豆"
        },
        {
            date:"2022/09/03",
            memo:"hogehoge",
            name:"ビール"
        }
    ]

    // データ属性指定で、繰り返すDOMを取得する
    var templateOriginal = $("[data-js-each=table-list-items]")

    // 複製元のDOMを非表示にする（Pugファイルに記載されているのはあくまで”テンプレート”として活用する）
    templateOriginal.hide()

    list.forEach((item, index) => {
        // data属性指定で、複製したDOMを操作する
        // 下記、メソッド化してさらにスマートにできそうですね！
        var template = templateOriginal.clone().wrap('<div>').parent()
        template.find('[data-js-text=date]').each((_, elem) => {
            $(elem).text(item.date)
        })
        template.find('[data-js-text=name]').each((_, elem) => {
            $(elem).text(item.name)
        })
        template.find('[data-js-text=memo]').each((_, elem) => {
            $(elem).text(item.memo)
        })

        //　操作したDOMを、指定した箇所の最後に追加して、表示する
        template.children().insertAfter("[data-js-each=table-list-items]:last").show()
    
    })
});

```


# まとめ

Pug記法で記述されたモックを基に、動的な処理を実装していく、という想定で説明しましたが、Pug記法で書いてる書いてない、にかかわらず、データ属性で操作していく”ステップ２”は、私のベストプラクティスかなと思います

いやいや、もっとスマートにかけるよ！という世の諸先輩方はぜひあなたのベストプラクティスをご教示ください！

ではまた！