你們可能會認為在HTML 中製作一個一致、乾淨且專業的旋轉框是一項簡單的任務...但是,令我們失望的是,沒有標準的屬性來告訴輸入它應該只接受整數或小數值,所有的輸入過濾都必須是JS。哎呀!
我將使用 Go、a-h/Templ、Tailwind 和我心愛的 Alpine.js 來實現此功能,讓生活變得輕鬆。
我們先為整數旋轉框寫一個基本模板:
templ IntSpinbox(name, label, value, tooltip string, saveinput bool, interval *IntInterval) { ... }
我們定義 IntInterval 如下:
type IntInterval struct { A, B int }
通過間隔,我們將設定輸入的最小值和最大值。當我們製作整數旋轉框時,步長將始終設定為“1”。
templ IntSpinbox(name, label, value, tooltip string, saveinput bool, interval *IntInterval) { <input type="number" placeholder="Enter Int…" step="1" if interval != nil { min={ strconv.Itoa(interval.A) } max={ strconv.Itoa(interval.B) } } ...> }
現在讓我們開始加入一些 tw 類,以下是一些控制輸入渲染的特殊屬性和偽元素。
select-none [-moz-user-select:none] [-ms-user-select:none] [-o-user-select:none] [-webkit-user-select:none]
以下額外類別用於刪除預設的微調按鈕:
[&::-webkit-inner-spin-button]:[-webkit-appearance:none] [&::-webkit-outer-spin-button]:[-webkit-appearance:none] [-moz-appearance:文字欄位]
最後,讓我們加入一些基本的填充、環、顏色等...
區塊w-full rounded-l-md py-2 px-2.5 text-gray-900ring-1ring-insetring-gray-300佔位符:text-gray-400焦點:outline-none焦點:ring-2焦點: ring -primary-400 bg-gray-50 sm:text-sm sm:leading-6
將其添加到我們的模板中,我們得到以下內容:
templ IntSpinbox(name, label, value, tooltip string, saveinput bool, interval *IntInterval) { <input type="number" placeholder="Enter Int…" step="1" if interval != nil { min={ strconv.Itoa(interval.A) } max={ strconv.Itoa(interval.B) } } class="block w-full rounded-l-md py-2 px-2.5 text-gray-900 ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:outline-none focus:ring-2 focus:ring-primary-400 bg-gray-50 sm:text-sm sm:leading-6 select-none [-moz-user-select:none] [-ms-user-select:none] [-o-user-select:none] [-webkit-user-select:none] [&::-webkit-inner-spin-button]:[-webkit-appearance:none] [&::-webkit-outer-spin-button]:[-webkit-appearance:none] [-moz-appearance:textfield]"> }
現在,如果將滑鼠懸停在其上,您應該會得到一個非常類似於文字的輸入,並進行一些基本驗證。我們將在下一節中加入檢查有效整數輸入的功能。
整數旋轉框的基本思想是僅接受整數的輸入。我最初嘗試使用HTML的pattern屬性來實現這個功能,如下所示:
<input type="number" pattern="[0-9]+" ... >
pattern 屬性採用正規表示式字串並使用它來驗證使用者輸入,但是,它並不能阻止輸入無效輸入。實際上,它是為了一些簡單的客戶端驗證而設計的。
每次使用者按下輸入框中的任意鍵時,都會產生 oninput 事件。使用 Alpine 的語法 x-on:input 擷取此事件,並相應地修正輸入元素的值。讓我們建立一個帶有 x-data 屬性集的父 div,並添加一個函數,該函數將允許我們檢查輸入是否完全是數字...之後我們可以相應地舍入該值。
<div x-data="{isNumber(n) { return !isNaN(parseFloat(n)) && !isNaN(n - 0) }}"> <input ... x-on:input="$el.value = isNumber($el.value) ? Math.round($el.value) : null"> </div>
對於不了解 Alpine 的人來說,這裡的 $el 用來引用目前的 DOM 元素。
在先前建立的父div 中,我們加入以下class="flex" 並在輸入中新增x-ref="spinbox" 屬性,以便我們的按鈕可以透過神奇屬性$refs.spinbox 修改其狀態:
<div ... class="flex"> <input ... x-ref="spinbox"> </div>
然後我們在輸入後新增一個新的子項,其中將包含我們的按鈕:
<div ...> <input ... x-ref="spinbox"> <div class="flex flex-col-reverse"> <!-- Decrement input's value --> <button type="button" class="flex-1 ...">-</button> <!-- Increment input's value --> <button type="button" class="flex-1 ...">+</button> </div> </div>
在這裡,我們使用 flex-col-reverse 作為保持 Tab 鍵順序正確的簡單方法,它應該首先 Tab 鍵到“-”,然後是“+”。
然後我們使用 x-on:click 將事件處理程序加入按鈕,完整程式碼(不包括 CSS)如下:
<div ... x-data="{ inc() { var e = $refs.spinbox; e.value = Math.min(Number(e.value) + Number(e.step), e.max); }, dec() { var e = $refs.spinbox; e.value = Math.max(Number(e.value) - Number(e.step), e.min); }, isNumber(n) { return !isNaN(parseFloat(n)) && !isNaN(n - 0) } }"> <input ... x-ref="spinbox" x-on:input="$el.value = isNumber($el.value) ? Math.round($el.value) : null"> <div ...> <!-- Decrement input's value --> <button type="button" ... x-on:click="dec">-</button> <!-- Increment input's value --> <button type="button" ... x-on:click="inc">+</button> </div> </div>
在進行任何算術之前,我們必須轉換 e.value 和 e.step,因為它們是字串。
當談到旋轉按鈕的 CSS 時,它們的樣式與輸入非常相似,完整的程式碼如下。
templ IntSpinbox(name, label, value, tooltip string, saveinput bool, interval *IntInterval) { <!-- Disable inner & outer spinner buttons, use buttons to render increment and decrement input value... --> <div class="flex-1"> @InputLabel(name, label + " " + interval.toString(), tooltip) <input type="number" placeholder="Enter Int…" step="1" if interval != nil { min={ strconv.Itoa(interval.A) } max={ strconv.Itoa(interval.B) } } name={ name } value={ value } class="block w-full rounded-l-md py-2 px-2.5 text-gray-900 ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:outline-none focus:ring-2 focus:ring-primary-400 bg-gray-50 sm:text-sm sm:leading-6 select-none [-moz-user-select:none] [-ms-user-select:none] [-o-user-select:none] [-webkit-user-select:none] [&::-webkit-inner-spin-button]:[-webkit-appearance:none] [&::-webkit-outer-spin-button]:[-webkit-appearance:none] [-moz-appearance:textfield]" x-on:input="$el.value = !isNumber($el.value) ? null : Math.round($el.value)" x-ref="spinbox" autocomplete="off" > <div class="flex flex-col-reverse font-medium"> <!-- Decrement input's value --> <button type="button" class="flex-1 px-1 leading-none transition-colors ease-linear duration-100 rounded-br-md text-center text-sm bg-gray-100 hover:bg-gray-200 text-gray-500 hover:text-gray-900 ring-1 ring-inset ring-gray-300 focus:outline-none focus:ring-inset focus:ring-2 focus:ring-primary-400 select-none [-moz-user-select:none] [-ms-user-select:none] [-o-user-select:none] [-webkit-user-select:none]" x-on:click="dec">-</button> <!-- Increment input's value --> <button type="button" class="flex-1 px-1 leading-none transition-colors ease-linear duration-100 rounded-tr-md text-center text-sm bg-gray-100 hover:bg-gray-200 text-gray-500 hover:text-gray-900 ring-1 ring-inset ring-gray-300 focus:outline-none focus:ring-inset focus:ring-2 focus:ring-primary-400 select-none [-moz-user-select:none] [-ms-user-select:none] [-o-user-select:none] [-webkit-user-select:none]" x-on:click="inc">+</button> </div> </div> </div> }
享受吧:)
以上是在 Go/Templ 中製作一個乾淨、友好的 Spinner的詳細內容。更多資訊請關注PHP中文網其他相關文章!