National Yunlin University of Science and Technology
Uedu Main Site
Explore Uedu
Student Console
Register as Member/Login
Research Informed Consent Center
Survey Center
Educational Big Data Challenge
Claim or create a course
Try a Scenario Task
Support & Messages
Uptime Data

UeduGPTs

--

Jupyters

1

Local AI

--

Uedu Code

--

雲林科技大學 AQI 56 27°C PM2.5 16
AI Reply Desktop Notifications

Show a desktop notification when the AI TA finishes replying

Chat Message Notifications

Notify me when classmates post messages in the forum

Sound notification

Play an alert sound whenever there is a new notification

Unit 20

表單

文字欄、單選、多選與下拉選單的讀取
Interaction 20 minute(s)

Learning Objectives

  • 說明表單由 form 與各種輸入欄位組成,並讀取文字欄、密碼欄與多行文字欄的 value
  • 用單選按鈕與下拉選單做單選項目,讀出使用者選了哪一個
  • 用核取方塊與多選下拉選單做多選項目,讀出所有勾選的項目
  • 處理 input、change、submit 事件,用 preventDefault 攔下送出,並用 FormData 一次取得所有欄位

表單:收集使用者的輸入

登入、報名、問卷、購物結帳,都是表單。HTML 表單由一個 <form> 加上許多輸入欄位組成:

<form action="/signup" method="post">
  <label for="user">帳號</label>
  <input type="text" id="user" name="user">
  <button type="submit">送出</button>
</form>
  • action:資料要送到哪個網址;method:送出的方式,get(預設,資料接在網址的查詢字串)或 post(資料放在請求內容裡)
  • 每個欄位的 name 是送出時的欄位名稱;沒有 name 的欄位不會被送出
  • <label for="user"> 對應 id="user" 的欄位:點標籤文字就等於點那個欄位,螢幕閱讀器也會唸出標籤

JavaScript 在表單上要做的事,就是讀出使用者填了什麼,並在送出之前檢查、整理(下一課的正規表示法會用來檢查格式)。

文字輸入欄

欄位 HTML
單行文字 <input type="text">
搜尋欄位 <input type="search">
密碼(輸入時顯示成圓點) <input type="password">
多行文字 <textarea></textarea>

不管哪一種,讀取與設定內容都用 value,讀到的一律是字串(即使使用者輸入的是數字):

const user = document.getElementById('user');
console.log(user.value);       // 目前的內容
user.value = '';               // 清空

要在使用者打字的同時做事(即時預覽、字數統計),監聽 input 事件:每改一個字就發生一次。 change 事件則要等內容改變而且離開欄位才發生。

互動練習:讀取文字欄

依任務幫欄位加上事件處理器,每次改完按「執行」,再到預覽裡輸入看看。

單選項目:單選按鈕與下拉選單

單選按鈕(radio button):name 相同的一組按鈕裡只能選一個;checked 屬性設定預設選項。

<label><input type="radio" name="shirt" value="S"> S</label>
<label><input type="radio" name="shirt" value="M" checked> M</label>

讀出選了哪一個:

const picked = document.querySelector('input[name="shirt"]:checked');   // 一個都沒選時是 null
console.log(picked ? picked.value : '還沒選');
console.log(form.elements.shirt.value);   // 也可以從表單的 elements 用 name 取得;沒選時是空字串

下拉選單(dropdown list):<select> 裡放好幾個 <option>,selected 屬性設定預設選項。

<select id="city" name="city">
  <option value="tp">臺北</option>
  <option value="kh" selected>高雄</option>
</select>
讀取 結果
city.value 選到的 <option> 的 value(沒寫 value 時就是選項文字)
city.selectedIndex 選到第幾個(從 0 開始)
city.options[city.selectedIndex].text 選到的選項顯示的文字,例如「高雄」
city.value = 'tp' 用程式改成選臺北

選項改變時發生 change 事件。選項少(2~5 個)時用單選按鈕,一眼就看得到所有選項;選項多時用下拉選單比較省空間。

互動練習:單選按鈕與下拉選單

範例先印出預設的尺寸 M 與地點 kh。依任務加上 change 處理器,改完按「執行」,再到預覽裡改選項。

想一想:文字欄與單選項目

1.

使用者在 <input id="age"> 輸入 20,document.getElementById('age').value 是什麼?

2.

一組單選按鈕要能「只選一個」,必須符合什麼條件?

3.

下拉選單裡選到的是 <option value="kh">高雄</option>,select.value 與 select.options[select.selectedIndex].text 分別是什麼?

4.

一組單選按鈕都沒有被選取時,document.querySelector('input[name="shirt"]:checked') 會得到什麼?

第 1 次作答

多選項目:核取方塊與多選下拉選單

核取方塊(checkbox):可以勾選零個、一個或好幾個,適合購物清單、待辦事項、多重選擇題。

<label><input type="checkbox" name="item" value="雞蛋" checked> 雞蛋</label>
<label><input type="checkbox" name="item" value="牛奶"> 牛奶</label>
  • 有沒有勾選看 checked(true/false);value 不管有沒有勾都是同一個值
  • 取得所有勾選的項目:document.querySelectorAll('input[name="item"]:checked'),再轉成陣列取出 value
  • 用程式勾選:box.checked = true

多選下拉選單:在 <select> 加上 multiple 屬性就能選好幾個,size 設定一次顯示幾個選項。 使用者要按住 Ctrl(Windows)或 command(Mac)才能多選,很多人不知道,所以一般建議用核取方塊。 讀取時,select.value 只會得到第一個選項,要用 select.selectedOptions 取得全部選到的 <option>:

const picked = Array.from(multi.selectedOptions).map(o => o.value);

互動練習:核取方塊與多選下拉選單

這是投影片的購物清單。依任務完成「結帳」與「全選」按鈕,以及多選下拉選單的讀取。

送出表單與 FormData

按下表單裡的 <button type="submit">(或在文字欄按 Enter)會發生 submit 事件,瀏覽器預設會把資料送到 action 並載入新頁面。 用 JavaScript 處理表單時,第一件事通常是攔下這個預設動作:

form.addEventListener('submit', (e) => {
  e.preventDefault();               // 不要離開這一頁
  const fd = new FormData(form);    // 一次取得表單裡所有有 name 的欄位
  console.log(fd.get('name'));      // 單一個值
  console.log(fd.getAll('topic'));  // 同名的多個值(核取方塊)→ 陣列
});

監聽 form 的 submit,而不是按鈕的 click:使用者在文字欄按 Enter 也會送出表單,只聽按鈕的 click 會漏掉。

FormData 收集欄位的規則:

  • 只收有 name 的欄位;停用(disabled)的欄位不收
  • 單選按鈕只收選到的那一個;核取方塊只收有勾選的,沒勾的不會出現
  • for (const [key, value] of fd) 可以逐一取得;Object.fromEntries(fd) 可以轉成物件,但同名的多個值只會留下最後一個,有核取方塊時要另外用 getAll

之後學到 fetch 時,FormData 可以直接當作請求的內容送到伺服器。

互動練習:用 FormData 讀取整張表單

先不改程式,填好表單按「送出」,看主控台顯示的欄位。接著依任務寫 submit 處理器。每個任務都要填好表單再按一次「送出」。

想一想:表單事件與 FormData

1.

要在使用者每打一個字時就更新字數統計,應該監聽哪一個事件?

2.

下面的程式會印出什麼?

const fd = new FormData();
fd.append('topic', 'js');
fd.append('topic', 'css');
console.log(fd.get('topic'), fd.getAll('topic'));
3.

下面的程式會印出什麼?

const fd = new FormData();
fd.append('name', 'Amy');
fd.append('topic', 'js');
fd.append('topic', 'css');
console.log(Object.fromEntries(fd));
4.

表單裡有一個核取方塊 <input type="checkbox" name="agree">,使用者沒有勾選就送出,new FormData(form).get('agree') 是什麼?

第 1 次作答

重點精華回顧

  • 表單由 <form> 與輸入欄位組成;action 是送出的網址、method 是 get(預設)或 post;欄位要有 name 才會被送出,<label for> 對應欄位的 id。
  • 文字欄(text、search、password、textarea)用 value 讀寫,讀到的一律是字串。
  • 單選:單選按鈕用相同的 name 分成一組,用 :checked 找出選到的那個;下拉選單用 select.value,顯示文字用 options[selectedIndex].text。
  • 多選:核取方塊看 checked,用 querySelectorAll('…:checked') 取得所有勾選項目;多選下拉選單用 selectedOptions。
  • input 每次改變就發生,change 改變並離開欄位(或選項改變)才發生;表單送出監聽 form 的 submit,用 e.preventDefault() 攔下。
  • new FormData(form) 一次取得所有欄位:get 取第一個值、getAll 取全部;沒勾選的核取方塊不會出現。
這一課完成了!
Next lesson:檔案上傳與預覽
你目前沒有登入,學習進度只存在這個瀏覽器。 Login 後,進度會跟著帳號,換電腦也看得到。