Dandy Now!
  • [개발자의품격][부트캠프][1기][16차시] 부트스트랩 #3 | 생성
    2022년 03월 02일 16시 24분 41초에 업로드 된 글입니다.
    작성자: DandyNow
    728x90
    반응형

    부트스트랩 #3

    https://getbootstrap.com/

     

    1. Starter template 가져오기

    https://getbootstrap.com/docs/5.1/getting-started/introduction/#starter-template

    <!doctype html>
    <html lang="en">
      <head>
        <!-- Required meta tags -->
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
    
        <!-- Bootstrap CSS -->
        <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
    
        <title>Hello, world!</title>
      </head>
      <body>
        <h1>Hello, world!</h1>
    
        <!-- Optional JavaScript; choose one of the two! -->
    
        <!-- Option 1: Bootstrap Bundle with Popper -->
        <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
    
        <!-- Option 2: Separate Popper and Bootstrap JS -->
        <!--
        <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.10.2/dist/umd/popper.min.js" integrity="sha384-7+zCNj/IqJ95wo16oMtfsKbZ9ccEh31eOz1HGyDuCQ6wgnyJNSYdrPa03rtR1zdB" crossorigin="anonymous"></script>
        <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.min.js" integrity="sha384-QJHtvGhmr9XOIpI6YVutG+2QOK9T+ZnN4kzFN1RtK3zEFEIsxhlmWl5/YESvpZ13" crossorigin="anonymous"></script>
        -->
      </body>
    </html>

     

    2. 네비게이션바 가져오기

    https://getbootstrap.com/docs/5.1/examples/carousel/

    <header>
      <nav class="navbar navbar-expand-md navbar-dark fixed-top bg-dark">
        <div class="container-fluid">
          <a class="navbar-brand" href="#">Carousel</a>
          <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarCollapse" aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
          </button>
          <div class="collapse navbar-collapse" id="navbarCollapse">
            <ul class="navbar-nav me-auto mb-2 mb-md-0">
              <li class="nav-item">
                <a class="nav-link active" aria-current="page" href="#">Home</a>
              </li>
              <li class="nav-item">
                <a class="nav-link" href="#">Link</a>
              </li>
              <li class="nav-item">
                <a class="nav-link disabled">Disabled</a>
              </li>
            </ul>
            <form class="d-flex">
              <input class="form-control me-2" type="search" placeholder="Search" aria-label="Search">
              <button class="btn btn-outline-success" type="submit">Search</button>
            </form>
          </div>
        </div>
      </nav>
    </header>

     

     

    3. 입력 폼 만들기

    3.1 네비게이션바와 입력 폼 간의 간격 주기

    <style>
      main {
        margin-top: 70px;
      }
    </style>

     

    3.2 Horizontal form 적용을 위한 <main> 태그 생성, class="container" 으로 왼쪽 간격 주기

    <main class="container">
      <div>
        
      </div>
    </main>

     

    3.3 Horizontal form 붙이기

    https://getbootstrap.com/docs/5.1/forms/layout/#horizontal-form 

    <form>
      <div class="row mb-3">
        <label for="inputEmail3" class="col-sm-2 col-form-label">Email</label>
        <div class="col-sm-10">
          <input type="email" class="form-control" id="inputEmail3">
        </div>
      </div>
      <div class="row mb-3">
        <label for="inputPassword3" class="col-sm-2 col-form-label">Password</label>
        <div class="col-sm-10">
          <input type="password" class="form-control" id="inputPassword3">
        </div>
      </div>
      <fieldset class="row mb-3">
        <legend class="col-form-label col-sm-2 pt-0">Radios</legend>
        <div class="col-sm-10">
          <div class="form-check">
            <input class="form-check-input" type="radio" name="gridRadios" id="gridRadios1" value="option1" checked>
            <label class="form-check-label" for="gridRadios1">
              First radio
            </label>
          </div>
          <div class="form-check">
            <input class="form-check-input" type="radio" name="gridRadios" id="gridRadios2" value="option2">
            <label class="form-check-label" for="gridRadios2">
              Second radio
            </label>
          </div>
          <div class="form-check disabled">
            <input class="form-check-input" type="radio" name="gridRadios" id="gridRadios3" value="option3" disabled>
            <label class="form-check-label" for="gridRadios3">
              Third disabled radio
            </label>
          </div>
        </div>
      </fieldset>
      <div class="row mb-3">
        <div class="col-sm-10 offset-sm-2">
          <div class="form-check">
            <input class="form-check-input" type="checkbox" id="gridCheck1">
            <label class="form-check-label" for="gridCheck1">
              Example checkbox
            </label>
          </div>
        </div>
      </div>
      <button type="submit" class="btn btn-primary">Sign in</button>
    </form>

     

     

    3.4 Inline radios 버튼 적용(https://getbootstrap.com/docs/5.1/forms/checks-radios/#inline)

    <div class="form-check form-check-inline">
      <input class="form-check-input" type="radio" name="inlineRadioOptions" id="inlineRadio1" value="option1">
      <label class="form-check-label" for="inlineRadio1">1</label>
    </div>
    <div class="form-check form-check-inline">
      <input class="form-check-input" type="radio" name="inlineRadioOptions" id="inlineRadio2" value="option2">
      <label class="form-check-label" for="inlineRadio2">2</label>
    </div>
    <div class="form-check form-check-inline">
      <input class="form-check-input" type="radio" name="inlineRadioOptions" id="inlineRadio3" value="option3" disabled>
      <label class="form-check-label" for="inlineRadio3">3 (disabled)</label>
    </div>

     

    3.5 Button addons으로 주소찾기(https://getbootstrap.com/docs/5.1/forms/input-group/#button-addons)

    <div class="input-group mb-3">
      <input type="text" class="form-control" placeholder="Recipient's username" aria-label="Recipient's username" aria-describedby="button-addon2">
      <button class="btn btn-outline-secondary" type="button" id="button-addon2">Button</button>
    </div>

     

     

    3.6 폼 수정

    3.3 ~ 3.5의 부트스트랩을 가져와서 폼에 적용한다. 폼의 모든 항목에 required를 적용한다. 수정된 폼은 다음과 같다.

    <form>
      <div class="row mb-3">
        <label for="name" class="col-sm-2 col-form-label">Name</label>
        <div class="col-sm-10">
          <input type="text" class="form-control" id="name" required />
        </div>
      </div>
      <div class="row mb-3">
        <label for="gender" class="col-sm-2 col-form-label">Gender</label>
        <div class="col-sm-10">
          <!-- Inline 라디오 버튼 적용 https://getbootstrap.com/docs/5.1/forms/checks-radios/#inline -->
          <div class="form-check form-check-inline">
            <input
              class="form-check-input"
              type="radio"
              name="gender"
              id="male"
              value="male"
              checked
            />
            <label class="form-check-label" for="male">남자</label>
          </div>
          <div class="form-check form-check-inline">
            <input
              class="form-check-input"
              type="radio"
              name="gender"
              id="female"
              value="female"
            />
            <label class="form-check-label" for="female">여자</label>
          </div>
        </div>
      </div>
      <div class="row mb-3">
        <label for="company" class="col-sm-2 col-form-label">Company</label>
        <div class="col-sm-10">
          <input type="text" class="form-control" id="company" required />
        </div>
      </div>
      <div class="row mb-3">
        <label for="email" class="col-sm-2 col-form-label">Email</label>
        <div class="col-sm-10">
          <input type="email" class="form-control" id="email" required />
        </div>
      </div>
      <div class="row mb-3">
        <label for="phone" class="col-sm-2 col-form-label">Phone</label>
        <div class="col-sm-10">
          <input type="tel" class="form-control" id="phone" required />
        </div>
      </div>
      <div class="row mb-3">
        <label for="address" class="col-sm-2 col-form-label">Address</label>
        <div class="col-sm-10">
          <!-- Button addons으로 주소찾기 https://getbootstrap.com/docs/5.1/forms/input-group/ -->
          <div class="input-group mb-3">
            <input
              type="text"
              class="form-control"
              placeholder="주소"
              id="address"
              aria-label="주소"
              aria-describedby="button-address"
              required
            />
            <button
              class="btn btn-outline-secondary"
              type="button"
              id="button-address"
            >
              주소찾기
            </button>
          </div>
        </div>
      </div>
    </form>

     

    4. 저장/목록 버튼 생성

    <form> 안에 버튼을 넣어준다.

    <div class="text-center">
      <button class="btn btn-primary">저장</button>
      <button class="btn btn-secondary">목록</button>
    </div>

     

    5. 자바스크립트 함수 작성

    5.1 submit이 되지않도록 처리

    async function doCreate() {
            event.preventDefault();

     

    5.2 <form>에 onsubmit 적용

    <form onsubmit="doCreate();">
    </form>

     

    5.3 <input>에 전화번호 형식 체크를 위한 pattern 적용

    <input
      type="tel"
      class="form-control"
      id="phone"
      pattern="^010-\d{3,4}-\d{4}$"
      required
    />

     

    5.4 주소찾기 기능위한 openDaumAPI 연동

    openDaumAPI 스크립트를 추가한다.

    <script src="//t1.daumcdn.net/mapjsapi/bundle/postcode/prod/postcode.v2.js"></script>

     

    주소찾기 버튼의 onclick 추가

    <button
      class="btn btn-outline-secondary"
      type="button"
      id="button-address"
      onclick="openDaumAPI();"
    >
      주소찾기
    </button>

     

    openDaumAPI 함수 수정

    document.querySelector(
                  "#address"
                ).value = `(${data.zonecode}) ${data.address}`;

     

    5.5 sweetalert 적용

    sweetalert 스크립트를 추가한다. 

    <script src="//cdn.jsdelivr.net/npm/sweetalert2@11"></script>

     

    doCreate 함수에 sweetalert을 적용한다.

    Swal.fire({
      title: "정말 저장하시겠습니까?",
      //   text: "삭제된 데이터는 복원되지 않습니다!",
      icon: "warning",
      showCancelButton: true,
      confirmButtonColor: "#3085d6",
      cancelButtonColor: "#d33",
      confirmButtonText: "저장",
      cancelButtonText: "취소",
    }).then(async (result) => {
      if (result.isConfirmed) {
        const res = await fetch("http://localhost:3000/customers", {
          method: "POST",
          body: JSON.stringify({
            name,
            gender,
            company,
            email,
            phone,
            address,
          }),
          headers: {
            "content-type": "application/json;charset=UTF-8",
          },
        });
    
        if (res.status === 201) {
          Swal.fire(
            "저장 성공!",
            "데이터가 정상적으로 저장 되었습니다.",
            "success"
          );
        } else {
          Swal.fire("고객 정보를 생성하지 못했습니다. 다시 시도하세요.");
        }
      }
    });

     

    6. 최종 코드

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <!-- Required meta tags -->
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
    
        <!-- Bootstrap CSS -->
        <link
          href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css"
          rel="stylesheet"
          integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3"
          crossorigin="anonymous"
        />
    
        <title>Hello, world!</title>
    
        <!-- 3.1 네비게이션바와 입력 폼 간의 간격 주기 -->
        <style>
          main {
            margin-top: 70px;
          }
        </style>
      </head>
      <body>
        <!-- 2. 네비게이션바 가져오기(https://getbootstrap.com/docs/5.1/examples/carousel/)-->
        <header>
          <nav class="navbar navbar-expand-md navbar-dark fixed-top bg-dark">
            <div class="container-fluid">
              <a class="navbar-brand" href="#">부트스트랩 실습</a>
              <button
                class="navbar-toggler"
                type="button"
                data-bs-toggle="collapse"
                data-bs-target="#navbarCollapse"
                aria-controls="navbarCollapse"
                aria-expanded="false"
                aria-label="Toggle navigation"
              >
                <span class="navbar-toggler-icon"></span>
              </button>
              <div class="collapse navbar-collapse" id="navbarCollapse">
                <ul class="navbar-nav me-auto mb-2 mb-md-0">
                  <li class="nav-item">
                    <a class="nav-link active" aria-current="page" href="#">Home</a>
                  </li>
                  <li class="nav-item">
                    <a class="nav-link" href="#">Link</a>
                  </li>
                  <li class="nav-item">
                    <a class="nav-link disabled">Disabled</a>
                  </li>
                </ul>
                <form class="d-flex">
                  <input
                    class="form-control me-2"
                    type="search"
                    placeholder="Search"
                    aria-label="Search"
                  />
                  <button class="btn btn-outline-success" type="submit">
                    Search
                  </button>
                </form>
              </div>
            </div>
          </nav>
        </header>
    
        <!-- 3.3 Horizontal form 붙이기(https://getbootstrap.com/docs/5.1/forms/layout/#horizontal-form) -->
        <main>
          <!-- 3.2 Horizontal form 적용을 위한 <main> 태그 생성, class="container" 으로 왼쪽 간격 주기 -->
          <div class="container">
            <!-- 5.2 <form>에 onsubmit 적용 -->
            <form onsubmit="doCreate();">
              <div class="row mb-3">
                <label for="name" class="col-sm-2 col-form-label">Name</label>
                <div class="col-sm-10">
                  <input type="text" class="form-control" id="name" required />
                </div>
              </div>
              <div class="row mb-3">
                <label for="gender" class="col-sm-2 col-form-label">Gender</label>
                <div class="col-sm-10">
                  <!-- 3.4 Inline radios 버튼 적용(https://getbootstrap.com/docs/5.1/forms/checks-radios/#inline) -->
                  <div class="form-check form-check-inline">
                    <input
                      class="form-check-input"
                      type="radio"
                      name="gender"
                      id="male"
                      value="male"
                      checked
                    />
                    <label class="form-check-label" for="male">남자</label>
                  </div>
                  <div class="form-check form-check-inline">
                    <input
                      class="form-check-input"
                      type="radio"
                      name="gender"
                      id="female"
                      value="female"
                    />
                    <label class="form-check-label" for="female">여자</label>
                  </div>
                </div>
              </div>
              <div class="row mb-3">
                <label for="company" class="col-sm-2 col-form-label">Company</label>
                <div class="col-sm-10">
                  <input type="text" class="form-control" id="company" required />
                </div>
              </div>
              <div class="row mb-3">
                <label for="email" class="col-sm-2 col-form-label">Email</label>
                <div class="col-sm-10">
                  <input type="email" class="form-control" id="email" required />
                </div>
              </div>
              <div class="row mb-3">
                <label for="phone" class="col-sm-2 col-form-label">Phone</label>
                <div class="col-sm-10">
                  <!-- 5.3 <input>에 전화번호 형식 체크를 위한 pattern 적용 -->
                  <input
                    type="tel"
                    class="form-control"
                    id="phone"
                    pattern="^010-\d{3,4}-\d{4}$"
                    required
                  />
                </div>
              </div>
              <div class="row mb-3">
                <label for="address" class="col-sm-2 col-form-label">Address</label>
                <div class="col-sm-10">
                  <!-- 3.5 Button addons으로 주소찾기 https://getbootstrap.com/docs/5.1/forms/input-group/ -->
                  <div class="input-group mb-3">
                    <input
                      type="text"
                      class="form-control"
                      placeholder="주소"
                      id="address"
                      aria-label="주소"
                      aria-describedby="button-address"
                      required
                    />
                    <!-- 5.4 주소찾기 기능위한 openDaumAPI 연동 -->
                    <button
                      class="btn btn-outline-secondary"
                      type="button"
                      id="button-address"
                      onclick="openDaumAPI();"
                    >
                      주소찾기
                    </button>
                  </div>
                </div>
              </div>
              <!-- 4. 저장/목록 버튼 생성 -->
              <div class="text-center">
                <button class="btn btn-primary">저장</button>
                <button class="btn btn-secondary">목록</button>
              </div>
            </form>
          </div>
        </main>
    
        <!-- Optional JavaScript; choose one of the two! -->
    
        <!-- Option 1: Bootstrap Bundle with Popper -->
        <script
          src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"
          integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p"
          crossorigin="anonymous"
        ></script>
    
        <!-- Option 2: Separate Popper and Bootstrap JS -->
        <!--
        <script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.10.2/dist/umd/popper.min.js" integrity="sha384-7+zCNj/IqJ95wo16oMtfsKbZ9ccEh31eOz1HGyDuCQ6wgnyJNSYdrPa03rtR1zdB" crossorigin="anonymous"></script>
        <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.min.js" integrity="sha384-QJHtvGhmr9XOIpI6YVutG+2QOK9T+ZnN4kzFN1RtK3zEFEIsxhlmWl5/YESvpZ13" crossorigin="anonymous"></script>
        -->
    
        <!-- 5.4 주소찾기 기능위한 openDaumAPI 연동 -->
        <script src="//t1.daumcdn.net/mapjsapi/bundle/postcode/prod/postcode.v2.js"></script>
    
        <!-- 5.5 sweetalert 적용 -->
        <script src="//cdn.jsdelivr.net/npm/sweetalert2@11"></script>
    
        <!-- 5. 자바스크립트 코드 -->
        <script>
          async function doCreate() {
            // 5.1 submit이 되지않도록 처리
            event.preventDefault();
    
            const name = document.querySelector("#name").value.trim();
            const gender = document.querySelector("[name=gender]:checked").value;
            const company = document.querySelector("#company").value.trim();
            const email = document.querySelector("#email").value.trim();
            const phone = document.querySelector("#phone").value.trim();
            const address = document.querySelector("#address").value.trim();
    
            // 5.5 sweetalert 적용
            Swal.fire({
              title: "정말 저장하시겠습니까?",
              //   text: "삭제된 데이터는 복원되지 않습니다!",
              icon: "warning",
              showCancelButton: true,
              confirmButtonColor: "#3085d6",
              cancelButtonColor: "#d33",
              confirmButtonText: "저장",
              cancelButtonText: "취소",
            }).then(async (result) => {
              if (result.isConfirmed) {
                const res = await fetch("http://localhost:3000/customers", {
                  method: "POST",
                  body: JSON.stringify({
                    name,
                    gender,
                    company,
                    email,
                    phone,
                    address,
                  }),
                  headers: {
                    "content-type": "application/json;charset=UTF-8",
                  },
                });
    
                if (res.status === 201) {
                  Swal.fire(
                    "저장 성공!",
                    "데이터가 정상적으로 저장 되었습니다.",
                    "success"
                  );
                } else {
                  Swal.fire("고객 정보를 생성하지 못했습니다. 다시 시도하세요.");
                }
              }
            });
          }
    
          function checkEmail() {
            const email = document.querySelector("#email").value;
            if (email !== "") {
              const regexpEmail =
                /^([a-z]+\d*)+(\.?[a-z]*)+@[a-z]+(\.[a-z]{2,3})+$/;
              if (!regexpEmail.test(email)) {
                document.querySelector("#emailMsg").style.display = "block";
              } else {
                document.querySelector("#emailMsg").style.display = "none";
              }
            } else {
              document.querySelector("#emailMsg").style.display = "none";
            }
          }
    
          function checkPhone() {
            const phone = document.querySelector("#phone").value;
            if (phone !== "") {
              const regexpPhone = /^010-\d{3,4}-\d{4}$/;
              if (!regexpPhone.test(phone)) {
                document.querySelector("#phoneMsg").style.display = "block";
              } else {
                document.querySelector("#phoneMsg").style.display = "none";
              }
            } else {
              document.querySelector("#phoneMsg").style.display = "none";
            }
          }
    
          function openDaumAPI() {
            new daum.Postcode({
              oncomplete: function (data) {
                // 팝업에서 검색결과 항목을 클릭했을때 실행할 코드를 작성하는 부분입니다.
                // 예제를 참고하여 다양한 활용법을 확인해 보세요.
                console.log(data);
                document.querySelector(
                  "#address"
                ).value = `(${data.zonecode}) ${data.address}`; // 5.4 주소찾기 기능위한 openDaumAPI 연동
                // document.querySelector("#zonecode").value = data.zonecode;
              },
            }).open();
          }
    
          function goToList() {
            document.location.href = "dom.html";
          }
    
          function doReset() {
            // document.location.reload();
    
            document.querySelector("#name").value = "";
            document.querySelector("#company").value = "";
            document.querySelector("#email").value = "";
            document.querySelector("#phone").value = "";
            document.querySelector("#address").value = "";
          }
    
          function checkEnter(e, id) {
            if (e.keyCode === 13) {
              document.querySelector("#" + id).focus();
            }
          }
    
          function checkEnterForPhone(e) {
            if (e.keyCode === 13) {
              openDaumAPI();
            }
          }
        </script>
      </body>
    </html>

     

    [그림 1] 입력 폼에 부트스트랩 적용

     

    728x90
    반응형
    댓글