# (Project) 表單驗證實作


## [Demo](https://michael0520.github.io/mission-19/index.html)
## HTML
### 首先 html 先建立 container  來包裹表單
```htmlembedded=
<div class='container'>
<form>

</form>
</div>
```
### 建立表單標籤,加上 id 為了之後可以控制整個表單(繼承原理)，加上標題
**(命名很重要，避免找不到)**
```htmlembedded=
<div class='container'>
<form id='form' class='form'>
<h2>Register to Us</h2> // 標題

</form>
</div>
```
### 開始建立表格
```htmlembedded=
<div class='container'>
<form id='form' class='form'>
<h2>Register to Us</h2> // 標題
<!--  username -->
<div class="form-control">
          <label for="username">Username</label>
          <input type="text" 
          class="username"
          id="username"
          placeholder="Enter username" />
          <small>Error message</small> // 錯誤要顯示的名字
        </div>
<!--  email -->
<div class="form-control">
          <label for="email">Email</label>
          <input type="text" 
          class="email" 
          id="email"
          placeholder="Enter email" />
          <small>Error message</small>
        </div>
<!--  password -->
        <div class="form-control">
          <label for="Password">Password</label>
          <input
            type="password"
            class="Password"
            id="password"
            placeholder="Enter password"
          />
          <small>Error message</small>
        </div>
<!--  confirm password -->
        <div class="form-control">
          <label for="confirmPassword">Confirm email</label>
          <input
            type="password"
            class="confirmPassword"
            id="confirmPassword"
            placeholder="Enter password again"
          />
          <small>Error message</small>
        </div>
<!--   加入button      -->
    <button type='submit'>Submit</button>
</form>
</div>
```

---
## Css

### 首先先選擇要使用的字體
> 1. 到達 [Google fonts](https://fonts.google.com/) 的官網
> 2. 輸入要使用的字體，這個專案是使用 Open Sans
> 3. 按下 Select this styles
> 4. 切換到 import 複製 import 以及 font-family 做使用
![Google fonts 範例](https://cdn.hashnode.com/res/hashnode/image/upload/v1664458755730/ANV_TAkvV.png)
#### 貼上複製好的 import 字體
```css=
@import url('https://fonts.googleapis.com/css2?family=Open+Sans:wght@300&display=swap');
```
### 開始排版
```css=
@import url('https://fonts.googleapis.com/css?family=Open+Sans&display=swap');

/* 存取固定要用的顏色，可用var()來呼叫 */
/* :root{
 * 固定語法兩個減號‘--’後面隨便
 * } */
:root {
  --success-color: #2ecc71;
  --error-color: #e74c3c;
}
/* 起手式 */
* {
  box-sizing: border-box;
}

body {
  background-color: #f9fafb;
  font-family: 'Open Sans', sans-serif;
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  margin: 0;
}

.container {
  background-color: #fff;
  border-radius: 5px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
  width: 400px;
}

h2 {
  text-align: center;
  margin: 0 0 20px;
}

.form {
  padding: 30px 40px;
}

.form-control {
  margin-bottom: 10px;
  padding-bottom: 20px;
  position: relative;
}

.form-control label {
  color: #777;
  display: block;
  margin-bottom: 5px;
}

.form-control input {
  border: 2px solid #f0f0f0;
  border-radius: 4px;
  display: block;
  width: 100%;
  padding: 10px;
  font-size: 14px;
}

.form-control input:focus {
  outline: 0;
  border-color: #777;
}

.form-control.success input {
  border-color: var(--success-color);
}

.form-control.error input {
  border-color: var(--error-color);
}
/* 將small 預設藏起 */
.form-control small {
  color: var(--error-color);
  position: absolute;
  bottom: 0;
  left: 0;
  visibility: hidden;
}
/* class 名稱增加一個 'error' 時，關閉躲藏 */
.form-control.error small {
  visibility: visible;
}

.form button {
  cursor: pointer;
  background-color: #3498db;
  border: 2px solid #3498db;
  border-radius: 4px;
  color: #fff;
  display: block;
  font-size: 16px;
  padding: 10px;
  margin-top: 20px;
  width: 100%;
}

```
---
## JS

### 先將會需要動到的標籤綁定起來

```javascript=
const form = document.getElementById('form')
const username =document.getElementById('username')
const email =document.getElementById('email')
const password =document.getElementById('password')
const confirmPassword =document.getElementById('confirmPassword')
```
### 設定監聽事件

```javascript=
form.addEventListener('submit',(e)=>{
  e.preventDefault(); // 讓此 submit 只執行一次
//   如果表格沒有填任何字串，就會呼叫 showError function
//   如果表格有填任何字串，就會呼叫 showSuccess function
  if(username.value===''){
    showError(username,'Username is required')
  }else{
    showSuccess(username);
    
})
```
### 寫 Error , Success function

```javascript=
// 如果失敗將會 更改 formControl 的 classname
// 更改為 'form-control error'
// 'form-control error' 的Css 設定為跑出紅色邊框
// 再將 small(警告紅字)綁上 id
// innerText 加上文字為，(message)參數,
// 上方 if 判斷式 message = 'Username is required'
// 所以紅字就會變成'Username is required'
const showError = ((input,message)=>{
  const formControl = input.parentElement;
  formControl.className = 'form-control error';
  const small = formControl.querySelector('small');
  small.innerText = message;
})

// 成功會變成綠邊框
const showSuccess = (input=>{
  const formControl = input.parentElement
  formControl.className='form-control success'
})
```
### 完成後再加上其他填空欄位的 if 判斷式

```javascript=
if(email.value===''){
    showError(email,'Email is required')
  }else{
    showSuccess(email);
  }
  if(password.value===''){
    showError(password,'Password is required')
  }else{
    showSuccess(password);
  }
  if(confirmPassword.value===''){
    showError(confirmPassword,'ConfirmPassword is required')
  }else{
    showSuccess(confirmPassword);
  }
```
以下為成功範例圖：
![成功範例圖](https://cdn.hashnode.com/res/hashnode/image/upload/v1664458757277/cGlo7ka-P.png)

### 撰寫 email 驗證

1. 因為 email 有較多形式，參考網路上現有的完美寫法，
2. Google search :  [js email regax](https://stackoverflow.com/questions/46155/how-to-validate-an-email-address-in-javascript)
3. 我們使用這段 
```javascript=
const re = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
    return re.test(String(email).toLowerCase());
```
4. 貼上程式碼，並命名寫為 function
```javascript=
const isValidEmail = (email=>{
  const re = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
    return re.test(String(email).toLowerCase());
})
```
5. 更改 email 的 if 判斷式為
```javascript=
if(email.value===''){
    showError(email,'Email is required')
//     加上這個 else if 去判斷
//     如果符合 isValidEmail function
//     就會跳Error 顯示字串更改為 is not valid
  }else if (!isValidEmail(email.value)) {
    showError(email,'Email is not valid')
  }
  else{
    showSuccess(email);
  }
```

[重構表單驗證](https://michael0520.github.io/2021/01/21/%E9%87%8D%E6%A7%8B%E4%BB%A5%E5%8F%8A%E9%80%B2%E9%9A%8E%E8%A1%A8%E5%96%AE%E9%A9%97%E8%AD%89/)

