Form Handling
In the earlier Reference Attributes article, we already introduced the basic usage of obtaining variable references through the & syntax. In real development, the values of form elements often need to stay synchronized with state variables, so reference attributes are especially important in form handling scenarios. This section focuses on the usage details of reference attributes on form elements, explaining how this mechanism can be used to efficiently access and control form data and achieve reactive data binding and updates.
Text Input
In the Form Input Handling section of the reference attributes article, we introduced how to use the &value reference attribute on an input tag to synchronize the input content with a variable in the embedded script. Similarly, textarea supports the same pattern:
<lang-js>
let inputValue = "Initial value"
</lang-js>
<p>The inputValue is: {inputValue}</p>
<textarea &value={inputValue}></textarea>
In addition, the input tag can also accept a &number reference attribute, which synchronizes the input value to the target variable after converting it into a number:
<lang-js>
let numericValue = 0
</lang-js>
<p>The numericValue is: {numericValue}</p>
<input type="number" &number={numericValue} />
&number reference attribute sets the target variable to NaN when the input value cannot be converted into a valid number. For this reason, it is usually intended to be used together with type="number" on the input tag so that the input stays valid.
Checkbox and Radio
For radio buttons and checkboxes, you can add &checked to synchronize the checked state with a variable value:
<lang-js>
let radioChecked = false
let checkboxChecked = false
</lang-js>
<input
type="radio"
&checked={radioChecked}
/>
<input
type="checkbox"
&checked={checkboxChecked}
/>
<p>radio: {radioChecked ? "" : "not"} checked</p>
<p>checkbox: {checkboxChecked ? "" : "not"} checked</p>
Checkbox and Radio Groups
Sometimes you may need to synchronize the combined state of multiple radio buttons or checkboxes. In that case, you can use the &group attribute and pass in an Array or Set:
- js
- ts
<lang-js>
const checkedArr = []
const choices = ["Qingkuai", "JavaScript", "TypeScript"]
</lang-js>
<qk:spread #for={item, index of choices}>
<input
type="checkbox"
!id={"choice" + item}
&group={checkedArr}
/>
<label
!for={"choice" + item}
style="margin-right: 20px;"
>
{item}
</label>
</qk:spread>
<qk:spread #for={item, index of choices}>
<p>{item}: {checkedArr[index] ? "" : "not"} checked</p>
</qk:spread>
<lang-ts>
const checkedArr: boolean[] = []
const choices = ["Qingkuai", "JavaScript", "TypeScript"]
</lang-ts>
<qk:spread #for={item, index of choices}>
<input
type="checkbox"
!id={"choice" + item}
&group={checkedArr}
/>
<label
!for={"choice" + item}
style="margin-right: 20px;"
>
{item}
</label>
</qk:spread>
<qk:spread #for={item, index of choices}>
<p>{item}: {checkedArr[index] ? "" : "not"} checked</p>
</qk:spread>
Select
The select tag can use the &value reference attribute to synchronize the selected item:
<lang-js>
let selected = "TypeScript"
const choices = ["Qingkuai", "JavaScript", "TypeScript"]
</lang-js>
<select &value={selected}>
<option
!value={item}
#for={item of choices}
>
{item}
</option>
</select>
<p>Your selected: {selected}</p>
For a multi-select select, you can pass an Array or Set to &value. In that case, the target may be a constant because Qingkuai only calls its methods and does not modify the target itself:
<lang-js>
const selectedItems = ["Qingkuai", "TypeScript"]
const choices = ["Qingkuai", "JavaScript", "TypeScript"]
</lang-js>
<select
multiple
&value={selectedItems}
>
<option
!value={item}
#for={item of choices}
>
{item}
</option>
</select>
<p>Selected items: {selectedItems.join(", ")}</p>
Using a Set is completely equivalent:
<lang-js>
const selectedItems = new Set(["Qingkuai", "TypeScript"])
const choices = ["Qingkuai", "JavaScript", "TypeScript"]
</lang-js>
<select
multiple
&value={selectedItems}
>
<option
!value={item}
#for={item of choices}
>
{item}
</option>
</select>
<p>Selected items: {Array.from(selectedItems).join(", ")}</p>