Progress Bar

이 μ˜ˆμ œλŠ” λΆ€λ“œλŸ½κ²Œ μŠ€ν¬λ‘€λ˜λŠ” 진행 λ°”λ₯Ό κ΅¬ν˜„ν•˜λŠ” 방법을 λ³΄μ—¬μ€λ‹ˆλ‹€.

μš°λ¦¬λŠ” /start둜 POST μš”μ²­μ„ 보내 μž‘μ—…μ„ μ‹œμž‘ν•˜λŠ” λ²„νŠΌμ΄ μžˆλŠ” 초기 μƒνƒœλ‘œ μ‹œμž‘ν•©λ‹ˆλ‹€:

<div hx-target="this" hx-swap="outerHTML">
  <h3>Start Progress</h3>
  <button class="btn primary" hx-post="/start">
            Start Job
  </button>
</div>

이 divλŠ” μƒνƒœμ™€ 진행 λ°”κ°€ ν¬ν•¨λœ μƒˆλ‘œμš΄ div둜 ꡐ체되며, 이 진행 λ°”λŠ” 600msλ§ˆλ‹€ μžλ™μœΌλ‘œ μƒˆλ‘œ κ³ μ³μ§‘λ‹ˆλ‹€:

<div hx-trigger="done" hx-get="/job" hx-swap="outerHTML" hx-target="this">
  <h3 role="status" id="pblabel" tabindex="-1" autofocus>Running</h3>

  <div
    hx-get="/job/progress"
    hx-trigger="every 600ms"
    hx-target="this"
    hx-swap="innerHTML">
    <div class="progress" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0" aria-labelledby="pblabel">
      <div id="pb" class="progress-bar" style="width:0%">
    </div>
  </div>
</div>

이 진행 λ°”λŠ” 600λ°€λ¦¬μ΄ˆλ§ˆλ‹€ μ—…λ°μ΄νŠΈλ˜λ©°, width μŠ€νƒ€μΌ 속성과 aria-valuenow 속성이 ν˜„μž¬ 진행 μƒνƒœλ‘œ μ„€μ •λ©λ‹ˆλ‹€. 진행 λ°” div에 IDκ°€ 있기 λ•Œλ¬Έμ—, htmxλŠ” μŠ€νƒ€μΌ 속성을 μƒˆλ‘œμš΄ κ°’μœΌλ‘œ μ„€μ •ν•˜λ©΄μ„œ μš”μ²­ μ‚¬μ΄μ˜ λ³€ν™”λ₯Ό λΆ€λ“œλŸ½κ²Œ μ „ν™˜ν•©λ‹ˆλ‹€. μ΄λŠ” CSS μ „ν™˜κ³Ό κ²°ν•©λ˜μ–΄ μ‹œκ°μ μΈ μ „ν™˜μ΄ λŠκΉ€ 없이 λΆ€λ“œλŸ½κ²Œ μ§„ν–‰λ©λ‹ˆλ‹€.

λ§ˆμ§€λ§‰μœΌλ‘œ, ν”„λ‘œμ„ΈμŠ€κ°€ μ™„λ£Œλ˜λ©΄ μ„œλ²„λŠ” HX-Trigger: done 헀더λ₯Ό λ°˜ν™˜ν•˜μ—¬ UIλ₯Ό β€œComplete” μƒνƒœλ‘œ μ—…λ°μ΄νŠΈν•˜λ©°, UI에 λ‹€μ‹œ μ‹œμž‘ λ²„νŠΌμ΄ μΆ”κ°€λ©λ‹ˆλ‹€(이 μ˜ˆμ œμ—μ„œλŠ” λ²„νŠΌμ— νŽ˜μ΄λ“œμΈ 효과λ₯Ό μΆ”κ°€ν•˜κΈ° μœ„ν•΄ class-tools ν™•μž₯을 μ‚¬μš©ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€):

<div hx-trigger="done" hx-get="/job" hx-swap="outerHTML" hx-target="this">
  <h3 role="status" id="pblabel" tabindex="-1" autofocus>Complete</h3>

  <div
    hx-get="/job/progress"
    hx-trigger="none"
    hx-target="this"
    hx-swap="innerHTML">
      <div class="progress" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="122" aria-labelledby="pblabel">
        <div id="pb" class="progress-bar" style="width:122%">
      </div>
    </div>
  </div>

  <button id="restart-btn" class="btn primary" hx-post="/start" classes="add show:600ms">
    Restart Job
  </button>
</div>

이 μ˜ˆμ œμ—μ„œλŠ” Bootstrap 진행 λ°”μ˜ μŠ€νƒ€μΌμ„ μ°Έμ‘°ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€.

.progress {
    height: 20px;
    margin-bottom: 20px;
    overflow: hidden;
    background-color: #f5f5f5;
    border-radius: 4px;
    box-shadow: inset 0 1px 2px rgba(0,0,0,.1);
}
.progress-bar {
    float: left;
    width: 0%;
    height: 100%;
    font-size: 12px;
    line-height: 20px;
    color: #fff;
    text-align: center;
    background-color: #337ab7;
    -webkit-box-shadow: inset 0 -1px 0 rgba(0,0,0,.15);
    box-shadow: inset 0 -1px 0 rgba(0,0,0,.15);
    -webkit-transition: width .6s ease;
    -o-transition: width .6s ease;
    transition: width .6s ease;
}
Server Requests ↑ Show

πŸ”—Demo