Bootstrap 5) Forms

이제 지~난한(ㅡㅡ;) Bootstrap 5 강좌의 긴 여정을 시작합니다..

Web 표준html로 웹사이트 틀을 만들고, css로 꾸며주고, Javascript로 동작시키는데.. 이것들은 각각 분리하여 작성되어야 나중에라도, 누구라도,, 알아보기 쉽고 유지 관리에도 도움이 된다!

Bootstrap 5 강좌는 html 5css 3의 대략적인 기본은 갖추고, 직접 코딩하고 검색하면서 스스로 학습하고자 하는 분들(만!)을 대상으로 합니다 ㅡㅡ;

폼 컨트롤

에 입력한 정보는 웹서버로 보내지고, 웹서버에서는 웹프로그램을 통해 폼을 처리한 뒤 그 결과를 받아 다시 브라우저로 돌려주게 된다 html에서의 Form 관련 내용은 본 강좌의 html 5) 폼 작성하기 부분을 참조하십시오..

폼 스타일 설정: .form-control
부트스트랩의 .form-control 클래스는 각각의 입력폼 컨트롤에 따르는 기본 모양 및 움직임을 표시해주는데, .form-control-lg/sm 클래스를 더하여 폼 컨트롤의 크기를 변경해줄 수도 있다:

그 전에 알아둘 것은, Bootstrap 5)에서는 <label>과 <input>의 관계가 완전히 재정의되었다는 점이다 - 구조적으로, <label> 안의 <input>와는 달리, 부트스트랩에서의 <input>와 <label>은 서로 분리된 형제요소이다!

                                    
                                        
                                    
                                
                                    
                                        
                                    
                                
                                    
                                        
                                    
                                
                                    
                                        
                                    
                                
                                    
                                        
                                    
                                
1. 폼 컨트롤에 disabled 속성을 더해주면; 폼 컨트롤에서의 포인터 이벤트 및 포커스가 불가능하게 된다. 한편, readonly 속성은 입력폼 선택 및 포커스는 가능하지만, 입력 필드값을 변경할 수는 없도록 한다:
                                    
                                        
                                    
                                
2. 입력폼 필드를 평문 스타일로 바꾸고자 한다면; .form-control.form-control-plaintext로 대체하여 기본 스타일을 제거해주면 된다:
                                    
                                        
                                    
                                
3. 입력폼 텍스트는 .form-text로 스타일을 지정하는데, 블록 레벨 요소가 사용된 경우에는 상단 여백이 추가된다:
Must be 8-20 characters long.
                                    
                                        
                                    
                                

폼 텍스트는 명시적으로 aria-describedby 속성을 써서 폼 컨트롤과 연결되어야 한다 - 이렇게 하면, 사용자가 컨트롤에 포커스를 주거나 입력할 때 스크린 리더기 등의 보조 기술이 이 폼 텍스트를 확실히 알려줄 것이다!


부트스트랩의 그리스시스템으로 작업할 때는 폼 요소를 .col 안에 넣어주어야 한다 부트스트랩은 내부적으로 고정된 높이를 설정하고, 브라우저간 약간의 불일치는 무시한다!

                                    
                                        
                                    
                                

플로팅 레이블(.form-floating)을 쓸 때는, <input> 요소가 <label> 앞으로 와야한다!

입력그룹

입력그룹: .input-group
우선, 입력그룹 사용 시 <label>은 입력그룹의 외부에 배치해야 한다. 다음, .input-group input-group-sm/lg 클래스로 입력그룹의 크기를 변경해줄 수 있는데, 내부 각 요소들의 크기는 .input-group에서 지정한 크기에 맞춰 자동으로 적절히 조정되며, 입력그룹 내부 개별 요소들에서의 독자적 크기 변경은 지원되지 않는다!
@
.form-text
                                    
                                        
                                    
                                
                                                    
                                                        
                                                    
                                                

체크폼 작성

Bootstrap 5)에서 브라우저 기본 체크박스라디오 버튼은 완전히 재정의되었다!

체크박스와 라디오버튼: .form-check
기본적으로, 체크박스나 라디오 버튼의 <input>와 <label>은 직계 형제요소이므로, 얼마든지 .form-check 클래스를 써서 쌓고 적절하게 간격을 줄 수 있다:
                                    
                                        
                                    
                                

를 제외한 나머지 컨트롤들은 스스로 작성해서 추가해주십시오.. 그저 위 <input> 요소에다 각각 checked, disabled, checked disabled 속성 키워드를 추가해주기만 하면 됩니다 ^^

                                    
                                        
                                    
                                

.form-check form-check-inline은 체크 폼을 인라인으로 배치한다 참고로, 라디오 버튼의 이름(name= "exampleRadios")은 모두 같아야 한다!


<label>에서 .form-check-label 대신, .btn 스타일을 사용하여 버튼 비슷한 체크박스나 라디오 버튼을 만들 수도 있다 이러한 토글 버튼은 필요 시, 버튼 그룹으로 추가로 그룹화할 수 있다!

                                    
                                        
                                    
                                
리버스 체크폼: .form-check form-check-reverse
.form-check에다 .form-check-reverse 클래스를 더하면 레이블과 체크 버튼의 순서를 바꾸어 뒤쪽서부터 배치한다:
                                    
                                        
                                    
                                

여기서는 뒤쪽으로 배치되면서, 동시에 레이블과 체크 버튼의 순서 또한 바뀌게 된다!

스위치 컨트롤: .form-check form-switch
폼에는 기본적인 체크박스 마크업이 있지만, 부트스트랩에서는 독자적으로 .form-check 클래스에 .form-switch 클래스를 더하여 토글 스위치를 렌더링한다:
                                    
                                        
                                    
                                

컨트롤의 특성을 보조기술에 더 정확하게 전달하고자 한다면; role= "switch" 속성을 넣어주는 것이 좋다!

선택상자 작성

선택 상자: .form-select
.form-select form-select-lg/sm 클래스는 <select> 선택상자의 크기를 변경하며, <option>에서의 .selected 클래스는 미리 선택된 항목으로 설정한다:
                                    
                                        
                                    
                                

처음에 펼쳐질 <option> 항목의 개수를 지정하려면; <select> 요소에서 size= "개수" 속성을 추가해주면 되는데, 옵션 항목 모두를 펼친 채 시작하려면; 대신에 multiple 속성을 추가해주면 된다:

참고로, multiple 속성을 주면; CtrlShift 키와의 조합으로 복수 선택을 가능하게 한다!

➥ <datalist>(& <option>)

html 5)에서 새로 도입된 <datalist>(& <option>) 요소는 <select>와 유사하지만, <select>(& <option>)과는 달리 메뉴 스타일링상의 더 많은 제약과 차이점이 있다!

                                        
                                            
                                        
                                    

<datalist>는 대부분의 브라우저에서 지원하기는 하지만, 아직은 브라우저간 일관성이 부족하다!

플로팅 레이블

플로팅 레이블
부트스트랩의 텍스트 폼 필드로 플로팅 레이블을 가능하게 하려면; .form-floating 내부에 <input class="form-control">과 <label> 요소를 필요로 하는데(플로팅 레이블에는 ~ 등의 형제 선택자를 사용하므로, <input>가 앞에 와야 한다!), 이때 ::placeholder-shown 가상요소 선택자가 사용되므로, 각 <input>에는 플레이스홀더 또한 필요하다:
                                    
                                        
                                    
                                
                                    
                                        
                                    
                                

<input>에서 value= 속성값이 이미 정의되어 있는 경우, <label>은 그에 맞춰 자동으로 위치를 조정하며, 양식 유효성 검사(.form-control is-invalid) 또한 예상대로 작동한다!

1. 부트스트랩의 .form-control에서 <textarea>는 기본적으로 <input>와 같은 높이를 갖는다. 따라서, 사용자정의 높이를 사용하고자 한다면; rows= 속성 대신, 명시적으로 인라인 style이나 css를 사용해야 한다:
                                    
                                        
                                    
                                
2. <select> 컨트롤에서도 .form-select 클래스를 주어 플로팅 레이블 기능을 사용할 수 있지만, 여기서는 <label>이 항상 떠있는 상태로 되며, sizemultiple 속성은 사용할 수 없다:
                                    
                                        
                                    
                                
3. 입력그룹(.input-group)과 .form-floating을 폼 유효성 검사와 함께 사용할 때는; 폼 피드백을 .form-floating 바깥에 배치해야 한다 이는 피드백이 자바스크립트를 사용하여 표시되어야 함을 의미한다!
@
Please choose a username
                                    
                                        
                                    
                                

폼의 유효성 검증

폼 유효성 검증
1. 입력 폼에서 required 속성을 주면; 브라우저에서 기본 제공하는 폼 유효성 검증을 사용할 수 있다:
@
                                                    
                                                        
                                                    
                                                
2. 사용자지정 폼 검증 메시지를 사용하고자 한다면; <form>에 novalidate 속성을 넣어주면 된다 (이 경우 브라우저 기본 피드백은 비활성화되지만, 여전히 자바스크립트의 폼 검증 API에 대한 액세스는 제공된다!) 한편, 폼 레이아웃에서 허용하는 경우, 폼 유효성 검증에 valid/invalid-feedback 클래스를 .valid/invalid-tooltip 클래스로 바꿀 수 있다:
Looks good!
Looks good!
@
Please choose a unique and valid username.
                                                    
                                                        
                                                    
                                                

툴팁의 포지셔닝을 위해, 부모요소에서 position:relative; 설정이 있어야 한다!

폼 레이아웃

부트스트랩에서 폼 필드의 모든 그룹은 <form> 안에 상주해야 한다. 부트스트랩은 대부분의 폼 컨트롤에서 display: block;, width: 100%;를 적용하므로, 폼은 기본적으로 세로로 쌓이게 된다!

폼 레이아웃
부트스트랩은 <form> 요소에 대한 기본 스타일링을 제공하지는 않지만, 기본적으로 제공되는 몇 가지 브라우징 기능이 있다. 예컨대, 폼 내부의 <button>들은 기본적으로 type= "submit"이므로, 항상 type 속성을 포함하여 구체적으로 지정하여야 한다. 또한, 폼 전체의 일관성을 위해서, 마진은 margin-bottom을 사용할 것을 권장한다:
Radios
                                                    
                                                        
                                                    
                                                

<legend>에는 관련 양식 컨트롤과 함께 수직 중앙에 위치하도록 .col-form-label 클래스를 추가해주어야 한다!

@
                                                    
                                                        
                                                    
                                                
                                                    
                                                        
                                                    
                                                

(* 이 샘플은 에서 가져온 것입니다.. )

툴팁/팝오버

원칙적으로 툴팁팝오버는 키보드로 초점을 맞출 수 있고, 대화형인 html 요소(예컨대, 링크 또는 폼 컨트롤)에만 사용해야 한다. 그렇지 않으면 키보드 및 스크린리더기 사용자들에게 불편하고 혼란스러운 상황을 야기시킬 수 있다!

툴팁/팝오버 작성하기
툴팁과 팝오버는 직접 초기화해야 하며, 숨겨진 요소나 길이가 0인 요소에서는 작동되지 않는다. 또한, .disabled 클래스(및 disabled 속성)인 요소에 대한 설명은 래퍼 요소에서 트리거되어야 하며, 해당 요소가 DOM에서 제거되기 전에 숨겨야 한다 페이지 내 모든 툴팁을 초기화하는 한 가지 방법은 data-bs-toggle 속성을 이용하는 것이다!
[ 툴팁/팝오버 초기화 스크립트 ]
                                        
                                            <body>
                                                ...
                                            
                                                <!-- 툴팁/팝오버를 위한 스크립트 코드 -->
                                                <script>
                                                    const tooltipTriggerList= document.querySelectorAll('[data-bs-toggle="tooltip"]')
                                                    const tooltipList= [...tooltipTriggerList].map(tooltipTriggerEl => new bootstrap.Tooltip(tooltipTriggerEl))
                                            
                                                    const popoverTriggerList= document.querySelectorAll('[data-bs-toggle="popover"]')
                                                    const popoverList= [...popoverTriggerList].map(popoverTriggerEl => new bootstrap.Popover(popoverTriggerEl))
                                                </script>
                                            </body>
                                        
                                    
1. 툴팁/팝오버에 필요한 html 마크업은 단지 data-bs-toggle= "tooltip/popover"data-bs-title= "툴팁/팝오버 설명" 속성 정도이다. 팝오버에서는 data-bs-content= "본문 내용" 속성도 사용할 수 있다:

                                    
                                        
                                    
                                

data-bs-title= "툴팁 설명" 대신 title= "툴팁 설명"으로 해도 같다 title은 Tooltip 및 Popover에 의해 자동으로 data-bs-title로 렌더링된다!

2. 툴팁과 팝오버 모두 data-bs-placement= "right/bottom/left"(기본값: top)로 나타날 위치를 지정해줄 수 있고, html 코드를 삽입하는 것도 가능하다 단, html 삽입은 스크린리더기 사용자에게는 불편한 스트림이 될 수도 있으므로 최대한 절제하여 쓰는 것이 좋다!

                                    
                                        
                                    
                                
3. disabled 속성이 있는 요소는 사용자가 툴팁 및 팝오버를 트리거하기 위해 포커스를 맞추거나 클릭할 수가 없다. 이런 경우에는, <div>나 <span>으로 둘러싸고 키보드 포커서블이 가능하도록 tabindex= "0" 속성을 주면 된다:

                                    
                                        
                                    
                                

disabled 팝오버 트리거의 경우에는, 사용자가 이 요소를 클릭하지 않고 지나칠 것으로 예상할 수 있으므로 (팝오버가 사용자에게 즉각적인 시각적 피드백으로 나타나도록)data-bs-trigger= "hover focus"를 제공해주는 것도 좋다!


토글 버튼이 아닌 다른 지점을 클릭할 때 팝오버가 해제되도록 하려면; 포커스 트리거를 사용할 수 있는데, 올바른 동작을 위해서는 <button> 태그가 아닌 <a> 태그를 써야하며, tabindex 속성도 포함해야 한다:

data-bs-trigger="focus" & tabindex="0"

                                    
                                        
                                    
                                
➥ 사용자정의 툴팁/팝오버

사용자정의 팝오버 사용 예:

                                    
                                        
                                    
                                
                                    
                                        .custom-popover {
                                            --bs-popover-max-width: 200px;
                                            --bs-popover-border-color: var(--bs-secondary);
                                            --bs-popover-header-bg: var(--bs-secondary);
                                            --bs-popover-header-color: var(--bs-white);
                                            --bs-popover-body-padding-x: 1rem; --bs-popover-body-padding-y: .5rem;
                                        }
                                    
                                

Alert 경고창

Alert 경고창은 사용자에게 알림 경고 메시지 및 일반적인 작업 상황에 맞는 피드백 메시지를 제공한다

Alert 기본
시각적 색상만을 통한 의미 전달은 스크린리더 사용자들에게는 제대로 인식되지 않을 수 있다. 이를 고려한다면, .visually-hidden 클래스 등을 추가하여 (숨겨진 텍스트를 써서)의미 전달을 명확히 해줄 필요가 있다!
                                    
                                        
                                    
                                
1. 경고를 해제하고 닫아두는 것도 가능한데, 단지 닫기 버튼을 만들어주기만 하면 된다. 우선, Alert 컨테이너(.alert)에서 .alert-dismissible 클래스(이는 .me-auto와 같은 역할을 한다!)로 닫기 버튼을 위한 우측 마진을 확보해준 다음, 컨테이너 내부에서 Alert 해제를 위한 [닫기]() 버튼을 만들어 배치해준다 - 이 <button> 요소에는 스크립트 기능을 트리거하는 data-bs-dismiss= "alert" 속성을 추가해주어야 한다:
                                    
                                        
                                    
                                

상자 해제 시 애니메이션을 적용하려면; .fade(흐릿하게) 및 .show(보이도록) 클래스를 더해야한다!

2. 버튼 클릭 등으로 Alert 메시지를 표시하는 것도 가능한데, 이를 해제하려면; Alert 트리거를 위한 스크립트 코드가 필요하다:
                                                    
                                                        
                                                    
                                                
                                                    
                                                        
                                                    
                                                

Toast 메시지

Toast 메시지는 푸시 메시지를 모방하도록 설계된 가벼운 알림 메시지로서, 플렉스박스로 제작되어 쉽게 정렬하고 배치할 수 있다!

Toast 메시지
Toast는 아래 방식과 같이 직접 초기화해야 하며, 달리 autohide: false;로 지정해준 것이 아니라면; 자동으로 숨겨진다 만약 토스트에 포커스 및 실행 가능한 컨트롤이 꼭 들어가야 한다면; autohide: false;로 설정해주어야 하며, 닫기 버튼도 반드시 넣어주어야 한다!
[ Toast 초기화 ]
                                        
                                            const toastTrigger= document.getElementById('liveToastBtn')
                                            const toastLiveExample= document.getElementById('liveToast')
                                    
                                            if (toastTrigger) {
                                                const toastBootstrap= bootstrap.Toast.getOrCreateInstance(toastLiveExample)
                                                toastTrigger.addEventListener('click', () => {
                                                    toastBootstrap.show();
                                                })
                                            }
                                        
                                    
1. 확장성과 예측 가능성을 고려한다면; 토스트는 toast-headertoast-body로 구성하는 것이 권장된다. 토스트 헤더는 플렉스박스를 사용하며, (자동으로 사라지기는 하지만)닫기 버튼도 넣어주는 것이 권장된다:
                                    
                                        
                                    
                                
2. 스크린리더기 등의 보조 기술에 대한 접근성을 고려한다면; 토스트가 나타나기 전에 .toast에서 aria-live= "polite", aria-atomic= "true" 값을 설정하여 aria-live를 둘러싸도록 한다. 나아가, 토스트 컨텐츠를 읽을 충분한 시간 지연도 설정해주는 것이 좋다(예컨대, data-bs-delay= "10000"):
[ 보조 기술을 위한 toast 코딩 ]
                                        
                                            
                                        
                                    

아래 코드들은 기본 샘플에서 색상 및 모양들을 조금씩 바꾸어준 것들인데, 필요 시 살펴보십시오..

                                                
                                                    
                                                
                                            
                                                
                                                    
                                                
                                            
                                                
                                                    
                                                
                                            
                                                
                                                    
                                                
                                            
                                                
                                                    
                                                
                                            

는 방문한 사용자에게 쿠키가 사용됨을 알려주는 가벼운 쿠키 동의 메시지 플러그인 라이브러리이다

부트스트랩 스크립트

거의 모든 부트스트랩 플러그인은 html의 data- 속성만으로 활성화하고 구성할 수 있는데, 하나의 요소에는 단지 하나의 데이터 속성 세트만 사용해야 한다 - 예컨대, 하나의 버튼으로 툴팁과 모달을 한번에 트리거할 수는 없다!

모달창
..
부트스트랩에서 스크립트 사용하기
모든 플러그인은 첫번째 인수로 css 선택자를 받아들일 수 있게 되었는데, DOM 요소 또는 적절한 css 선택자를 전달하여 플러그인의 새 인스턴스를 만들 수 있다. 스크립트 옵션은 data-bs- 속성이나 자바스크립트를 통해 전달할 수 있으므로, data-bs-animation= "값";과 같은 방식으로 줄 수 있다:
                                    
                                        const modal= new bootstrap.Modal('#myModal')
                                        const dropdown= new bootstrap.Dropdown('[data-bs-toggle="dropdown"]')
                                    
                                

* cf) Bootstrap 5) 버전에서부터 모든 자바스크립트 플러그인의 data- 속성은 기존의 data-*에서 data-bs-*로 이름이 변경되었는데, 옵션 이름은 camalCase 방식에서 kebab-case 방식으로 변경해주어야 한다! 한편, 부트스트랩에서 드롭다운, 팝오버 및 툴팁 등은 Popper 플러그인을 사용한다!

스크립트에서 DOM 요소를 쿼리할 때, 기본적으로 querySelectorquerySelectorAll 속성을 사용한다. 부트스트랩은 대부분의 플러그인 고유 작업에 대한 사용자정의 이벤트를 제공하는데, 일반적으로 show같은 동사 형태는 이벤트가 시작될 때 트리거되고, shown같은 과거분사 형태는 작업 완료 시 트리거된다:
                                    
                                        const myModal= document.querySelector('#myModal')
    
                                        myModal.addEventListener('show.bs.modal', event => {
                                            if (!data) {
                                                return event.preventDefault() // stops modal from being shown
                                            }
                                        })
                                    
                                

모든 동사 형태 이벤트는 preventDefault() 메서드를 제공하는데, 이는 작업이 시작되기 전에 실행을 중지하는 기능을 제공한다 이벤트 핸들러에서 false를 반환하면 자동으로 호출된다!

플러그인 인스턴스
특정 플러그인의 인스턴스를 얻고자 한다면; 각 플러그인은 getInstance(); 메서드를 노출하므로, 요소로부터 직접 인스턴스를 검색하려면 다음과 같이 하면 된다: bootstrap.Popover.getInstance(myPopoverE1); 요청된 요소에 대해 인스턴스가 시작되지 않은 경우 null이 리턴된다!
한편, getOrCreateInstance() 메서드는 DOM 요소와 연결된 인스턴스를 가져오거나, (없다면;)새로이 인스턴스를 만들어 반환한다: bootstrap.Popover.getOrCreateInstance(myPopoverE1, configObject); 인스턴스가 초기화되지 않은 경우, 두번째 인수를 받아 선택적 구성 객체로 사용한다!
                                    
                                        const modal= new bootstrap.Modal('#myModal')
                                        const dropdown= new bootstrap.Dropdown('[data-bs-toggle="dropdown"]')
                                        const offcanvas= bootstrap.Offcanvas.getInstance('#myOffcanvas')
                                        const alert= bootstrap.Alert.getOrCreateInstance('#myAlert')
                                    
                                

모든 플러그인 생성자는 DOM 요소 또는 적절한 css 선택자를 첫번째 인수로 받을 수 있는데, 부트스트랩은 단일 요소만 지원하므로 플러그인 요소들은 querySelector() 메서드로 찾을 수 있다!

비동기식 API
모든 프로그래밍 방식 API 메서드는 비동기식이며, 따라서 일단 트랜지션이 시작되면; 종료하기 전에 곧바로 호출자에게 반환되고, 트랜지션이 완성되면; 액션을 실행하기 위해 해당 이벤트를 수신할 수 있다. 한편, 트랜지션 컴포넌트에 대한 메서드 호출은 무시된다.
                                    
                                        const myCollapseEl= document.querySelector('#myCollapse')

                                        myCollapseEl.addEventListener('shown.bs.collapse', event => {
                                            // Action to execute once the collapsible area is expanded
                                        })
                                    
                                
                                    
                                        const myCarouselEl= document.querySelector('#myCarousel')
                                        const carousel= bootstrap.Carousel.getInstance(myCarouselEl) // Retrieve a Carousel instance

                                        myCarouselEl.addEventListener('slid.bs.carousel', event => {
                                            carousel.to('2') // Will slide to the slide 2 as soon as the transition to slide 1 is finished
                                        })

                                        carousel.to('1') // Will start sliding to the slide 1 and returns to the caller
                                        carousel.to('2') // !! Will be ignored, as the transition to the slide 1 is not finished !!
                                    
                                
버튼 인스턴스 만들기
부트스트랩의 .btn 생성자를 써서 버튼 인스턴스를 만들 수 있는데, dispose(), getInstance(), getOrCreateInstance() 외에 toggle()(버튼 활성화 상태를 토글한다) 메서드를 사용할 수 있다:
                                    
                                        const bsButton= new bootstrap.Button('#myButton');
                                
                                        // 모든 버튼을 토글한다
                                        document.querySelectorAll('.btn').forEach(buttonElement => {
                                            const button= bootstrap.Button.getOrCreateInstance(buttonElement)
                                            button.toggle()
                                        });
                                    
                                

* cf) 스크립트 API는 Javascript를 모르는 상태에서는 이해하기에 어렵고, 또 당장 쓸 일도 없을 터이니.. 대충, 대충,, 보시고 나중에 Javascript를 배우게 된다면; 그때 한번 다시 살펴보십시오 ㅡㅡ;

wave