그동안 modal 창이 필요할 때 부트스트랩을 자주 사용했었는데 이제(2022년? ㅎ) html의 기본 태그에도 modal 역할을 수행하는 녀석이 생겼다. 이름 하여 <dialog>
<dialog>
hello dialog?
dialog는 단순히 써볼 수 있는데 dialog를 보여주기 위해서는 open 속성을 사용하면 된다.
<dialog id="dialog1" open>
<p>안녕 난 다이어로그야!</p>
</dialog>
dialog의 기본 display는 none인데 open 상태일 경우는 block으로 변경된다. (미리 css 처리가 되어있고 이때 내부적으로는 HTMLDialogElement.show() 함수가 동작한다.)
position 속성은 absolute를 가지므로 top, left 등의 속성으로 위치를 제어하기 용이하다. 기본적으로는 가운데 상단에 배치된다.
이벤트를 이용한 dialog 제어
간단히 javascript를 이용해서 dialog를 제어해보자. model은 HTMLDialogElement 타입의 요소이며 다음의 주요 속성을 갖는다.
- open: 현재 dialog가 보여지는지 아닌지를 나타내는 boolean 값
- show(): dialog를 일반적인 block(display absolute)으로 보여줌
- showModel(): dialog를 modal 형태로 보여줌 - top layer를 구성하며 화면의 중앙에 보여줌
- close(): dialog를 닫음
또한 dialog는 close 이벤트에 대한 처리가 가능해서 닫히는 시점에 추가적인 작업이 가능하다.
<body>
<dialog id="dialog2">
<p>제어대상</p>
</dialog>
<menu>
<button id="showDialog2">dialog 2 toggle</button>
<button id="hideDialog2">hide</button>
</menu>
</body>
<script>
document.querySelector('#showDialog2').addEventListener('click', () => {
const dialog = document.querySelector('#dialog2');
if (!dialog.open) {
dialog.show(); // 현재 위치에서 보여줌
// dialog.showModal(); // 모달로 띄움 : 화면의 가운데 위치
} else {
dialog.close();
}
});
document.querySelector('#dialog2').addEventListener('close',
() => console.log('dialog 닫힘')
);
</script>
form 과의 협업
일반적으로 form을 이용해서 사용자의 입력을 받을 경우 dialog를 많이 사용하게 된다. 이를 위해 기존에는 form의 method에서 get/post만을 이용했었는데 dialog가 추가되었다.
<dialog id="dialog3">
<form method="dialog" id="myform"> <!--submit을 서버로 보내는 것이 아니라 dialog로 보낸다.-->
<input type="text" placeholder="id please" name="id" />
<input type="text" placeholder="name please" name="pass" />
<button id="confirm">제출</button> <!--submit 타입이 클릭되면 dialog는 닫힌다.-->
<button>닫기</button>
</form>
</dialog>
method가 dialog로 설정되면 submit 했을 때 값이 서버로 전달되는게 아니라 dialog가 받게 된다. dialog가 받는 값은 submit을 발생시킨 요소의 value이다. 따라서 화면 요소의 값들을 button의 value로 만드는 작업이 필요하다.
document.querySelector('#confirm').addEventListener('click', (e) => {
const formData = new FormData(document.querySelector('#myform'));
const json = {};
for (const [key, value] of formData.entries()) {
json[key] = value;
}
e.currentTarget.value = JSON.stringify(json); // 이벤트 소스에 값 설정
});
form에서 전달한 값은 dialog의 returnValue에서 확인할 수 있다. 이 returnValue 속성은 단순한 문자열이므로 JSON 객체등을 저장할 수는 없다.
document.querySelector('#dialog3').addEventListener('close', (e) => {
if (e.currentTarget.returnValue) {
// dialog의 returnValue 속성으로 값 확인 가능
console.log('입력 값: ', e.currentTarget.returnValue);
}
});