반응형

자주 유효성체크를 하게 될 로직은 아니므로 별도로 포스팅을 합니다.

 

사업자 번호 유효성 체크하는 방법을 알아보겠습니다.

 

검증절차

ex) 사업자번호: 123-45-67891

1. 사업자 번호는 10자리이다.(숫자만 있다고 가정)

2. 인증키값으로 체크하려는 사업자번호와 연산을 한다.

   (키값 = 1 3 7 1 3 7 1 3 5)

3. 사업자번호 앞 9자리  인증키 9자리의 각 자리수를 각각 곱하여 전부 더해줍니다.

    S = (1 * 1) + (2 * 3) + (3 * 7) + (4 * 1) + (5 * 3) ...  + (9 * 5)

4. 사업자번호 뒤에서 2번째자리와 인증키 마지막 값을 곱하고 10으로 나눈 후 위의 합과 추가로 더해줍니다.

    S += 9 * 5 / 10(소수점은 제거한다.)

5. 합계를 10으로 나머지 연산을 합니다.

   S % 10 = 9

6. 10에서 나머지 연산의 값을 빼줍니다.

   10 - 9 = 1

7. 사업자번호 마지막자리와 마지막 처리한값이 같으면 사업자번호입니다.

   1 = 1 사업자번호 O

 

 

 

구현 소스

function checkCorporateRegiNumber(number){
	var numberMap = number.replace(/-/gi, '').split('').map(function (d){
		return parseInt(d, 10);
	});
	
	if(numberMap.length == 10){
		var keyArr = [1, 3, 7, 1, 3, 7, 1, 3, 5];
		var chk = 0;
		
		keyArr.forEach(function(d, i){
			chk += d * numberMap[i];
		});
		
		chk += parseInt((keyArr[8] * numberMap[8])/ 10, 10);
		console.log(chk);
		return Math.floor(numberMap[9]) === ( (10 - (chk % 10) ) % 10);
	}
	
	return false;
}

 

반응형
반응형

모든 Controller(메소드)의 동작이 끝나고 로그를 처리하기 위해 SPRING AOP@after를 사용하여 기록을 하고 있었습니다.
작업 도중 파일 업로드를 위한 multipart의 타입의 전송의 경우 request의 값이 null값으로 처리되어 값을 받아 올 수 없었고 처리한 방법은 아래와 같이 2가지정도가 있었습니다.

  1. aop부분에서 형변환을 처리하여 값을 변경하였습니다.

  2. Interceptor에서 request의 타입을 체크하여 RequestContextHolder의 속성값을 변경하였습니다.

 

after어노테이션에서 형변환 방식

@After("execution(public * egovframework.*.*.*.*(..))")
public void logWrite(JoinPoint joinPoint) throws Throwable {
    final String methodName = joinPoint.getSignature().getName();
    ServletRequestAttributes attribute = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes());
    HttpServletRequest request = attribute.getRequest();

    // 멀티 파트 체크 **************
    if (request.getContentType() != null && request.getContentType().toLowerCase().contains("multipart/form-data")) {
        MultiReadAndCopyHttpServletRequest copyReq = new MultiReadAndCopyHttpServletRequest(request); //Request복사
        CommonsMultipartResolver cmResolver = new CommonsMultipartResolver();  //형식변환준비
        MultipartHttpServletRequest req = cmResolver.resolveMultipart(copyReq); //변환
        request = req;
    }
    // 멀티 파트 체크 **************

    (...) //이후 로그처리

첫번째 해결방식으로 reqeust의 값이 null인지 체크후 multipart/form-data인지 확인 후 일치한다면, requestMultipartHttpServletReqeust로 형변환처리하였습니다.

해당 방법으로 해결은 가능하지만 AOP의 양이 많아지거나 처리로직이 많아지면 가독성면이나 이후 유지보수 측면에서 좋지 않을것으로 판단하여 다른방법을 찾아보았고 Interceptor에서 처리하는 방법을 확인하였습니다.

 

 

Interceptor 추가하기

두번째 처리방법으로 Interceptor를 추가하고 instanceof를 통해 타입을 체크 후 변경해주도록 하였습니다.

 

MultipartHandlerInterceptor.java

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

/**
 * form태그 encType이 "multi/part"로 넘어갈경우 request set변경처리
 * @author srok
 *
 */
public class MultipartHandlerInterceptor extends HandlerInterceptorAdapter {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (request instanceof MultipartHttpServletRequest) {
            RequestContextHolder.setRequestAttributes(new ServletRequestAttributes(request));
        }
        return true;
    }
}

 

 

dispatcher-servlet.xml

Interceptor 정보 추가

<mvc:interceptors>
    <mvc:interceptor>
        <mvc:mapping path="/*.do" />
        <bean class="프로젝트 경로.MultipartHandlerInterceptor" />
    </mvc:interceptor>
</mvc:interceptors>

실 적용은 두번째 방식을 적용하였습니다.

 

 

 

두번째 처리방식 참조 URL

참조 : https://hhjeong.tistory.com/74

반응형
반응형

스프링 구조에서 3버전이 너무 낮아 4버전으로 올려서 프로젝트를 진행하던 중

java.lang.IllegalArgumentException: No converter found for return value of type: class java.util.ArrayList

 

같은 에러를 만나게 되었다.

 

컨트롤러에서 JSON형태로 LIST데이터를 리턴하면서 발생하는 에러로 아래와 같이 gson 라이브러리를 추가하여 해결하였다.

 

pom.xml

<dependency>
	<groupId>com.google.code.gson</groupId>
	<artifactId>gson</artifactId>
	<version>2.8.5</version>
</dependency>
반응형
반응형

클릭 이벤트를 처리하고자 할때, jQuery를 통해 보다 쉽게 이벤트를 정의할 수 있습니다.

on(), click(), bind(), onclick()등 여러가지 방법이 있는데, 제가 주로 사용하는 on()click()의 차이에 대해 알아보겠습니다.

 

 

click()

단순하게 정적페이지에 로드된 요소에 클릭이벤트를 처리하고자 할때 click()메소드를 자주 사용합니다. 해당 클릭이벤트는 동적처리가 불가능합니다.

 

다음 예제를 확인해보겠습니다.

 

See the Pen jQuery click by myhappyman (@myhappyman) on CodePen.

 

 

 

name속성이 save인 button요소를 클릭하면 click()이벤트 처리로 body태그에 click!!!을 찍어냅니다.

 

 

on()

이번엔 on() 메소드입니다.

on() 메소드는 주체가 되는 부모속성의 이벤트를 물려받아서 지정 선택자에게 이벤트를 연결할 수 있습니다.

물론 잘 못사용하면 click()이벤트처럼 정적으로 사용이 되므로 부모속성을 이용하여 처리한다는 이부분을 참고하셔야 합니다.

바로 예제를 확인해보겠습니다.

 

See the Pen jQuery on Click by myhappyman (@myhappyman) on CodePen.

 

 

 

ready안에 동작을 간단하게 설명해자면 HTML 내 클릭한 대상이 name값으로 add를 가지는 버튼 태그이면 body태그에 "+버튼"을 생성하는 예제입니다.

적용한 on()메소드의 파라미터를 확인해보겠습니다.

1. 첫번째 파라미터에는 행위(click, change, keypress 등)를 지정합니다. 이번 예제에서는 클릭을 처리하고 싶으므로 "click"으로 지정합니다.

 

2. 두번째 파라미터에는 지정자를 선택할 수 있습니다. name의 속성이 add인 버튼에 이벤트를 지정하고 싶으므로

"button[name='add']"으로 처리했습니다.


3. 세번째 파라미터는 구현부입니다. 콜백 메소드로 지정한 행위가 일어나면 콜백메소드에 정의한 내용이 동작합니다. body태그에 name속성이 add인 버튼을 생성하도록 append처리하였습니다.

 

동적으로 생성된 버튼도 동일한 동작을 한다.

 

 

동적으로 이벤트가 전부 할당되어 정상 동작하는 것을 볼 수 있습니다.

 

 

 

동적 이벤트 처리시 잘못된 방법

그럼 동적으로 처리하고자 할 때 잘못된 표현방법은 무엇일까요?

$("button[name='add']").on("click", function () {
    $("body").append("<button name='add'>+</button>");
});

부모요소가 name값이 add인 버튼에 바로 클릭이벤트를 처리하였습니다.

 

결과는 아래와 같습니다.

추가로 생성된 버튼은 동작하지 않는다.

이번엔 동일하게 on()메소드를 활용하였지만 동적으로 생성된 버튼은 동작하지 않습니다.

 

당연하게도 문서가 첫 로드되면서 이벤트는 현재 로드된 요소 중 name값이 add인 첫번째 버튼에만 클릭이벤트가 처리되고 이후에 동적으로 생성된 데이터는 연결되지 않았기 때문입니다.

 

이 부분을 유의해서 처리하시면 언제든지 동적으로 클릭이벤트뿐만 아니라 키이벤트 마우스이벤트등을 처리 할 수 있습니다.

반응형
반응형

javascript를 통해 자주 사용하는 유효성 체크 함수들을 남겨봅니다.

 

이메일 체크 정규식

function ValidateEmail(inputText) {
    var mailformat = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,3})+$/;
    if (mailformat.test(inputText)) {
        return true;
    } else {
        alert("입력하신 값은 이메일 형식이 아닙니다.");
        //focus 처리가 필요하면 이곳에! $("#email").focus();
        return false;
    }
}

사용 결과

//true
ValidateEmail("myhappyman@naver.com");  //true
ValidateEmail("myhappyman@test.co.kr");  //true


//false
ValidateEmail("myhappymantest.co.kr");  //false
ValidateEmail("myhappyman@naver.com2");  //false

IP 체크 정규식

function ValidateIPaddress(inputText) {
    var ipformat = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
    if (ipformat.test(inputText)) {
        return true;
    } else {
        alert("입력하신 값은 IP형식이 아닙니다.");
        //focus 처리가 필요하면 이곳에! $("#ip").focus();
        return false;
    }
}

사용 결과

//true
ValidateIPaddress("0.0.0.0");  //true
ValidateIPaddress("255.255.255.255");  //true

//false
ValidateIPaddress("0");  //false
ValidateIPaddress("-1.0.255.255");  //false
ValidateIPaddress("255.0.11.256");  //false

비밀번호 체크 정규식

비밀번호는 개발하면서 많은 포맷이 사용될텐데 주석을 통해 원하는 방식으로 변경하여 사용하거나 커스텀을 하면 좋을것 같다.

function ValidatePassword(inputText) {
    var pwformat = /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{6,20}$/;
    if (pwformat.test(inputText)) {
        return true;
    } else {
        alert("비밀번호 형식을 지켜주세요.\n비밀번호는 숫자, 소문자, 대문자를 1개이상, 6~20자리 이내로 입력해주세요.");
        return false;
    }
}

사용 결과

//true
ValidatePassword("fdsfdasQ2321!") //true
ValidatePassword("Ffdaf2321!") // true

//false
ValidatePassword("fdaf2321!") //false 대문자가 없음
ValidatePassword("QWERQWER!") //false 소문자가 없음
ValidatePassword("javascript") // false 대문자, 숫자가 없음

다른 정규식 방식

//비밀번호의 다양한 정규식
// * 하나 이상의 숫자와 특수 문자가 포함하는 7~15자 비밀번호
var pwformat = /^(?=.*[0-9])(?=.*[!@#$%^&*])[a-zA-Z0-9!@#$%^&*]{7,15}$/;

// * 하나 이상의 소문자, 대문자, 숫자 및 특수 문자를 포함하는 8~15자 비밀번호
var pwformat = /^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[^a-zA-Z0-9])(?!.*\s).{8,15}$/;

체크하는 정규식의 값만 변경 해주면 원하는 비밀번호 패턴을 체크할 수 있습니다.

출처 : https://www.w3resource.com/

반응형
반응형

필터에서 DB에서 받아온 정보를 사용하고 싶은 경우가 발생하였다.

 

초기화 함수인 init에서 서비스단이나 DAO를 사용하면 아직 bean등록이 되지 않은 상태로 초기화함수를 사용할 수 없었고 @PostConstruct를 활용하여 데이터를 처리할 수 있었다.

 

어찌저찌 처리는 하였지만 sysout을 통해 찍어보니 로그가 3번씩 찍히는 현상을 발견하였다.

 

구조부터 spring문서나 2번이상 발생되는 자료를 찾아봤지만 딱히 찾을 수 없었는데, 원인은 소스의 설정방법에 문제가 있었다.

 

해당 필터를 빈등록을 하기 위해 @Component 어노테이션을 설정하였다.

여기서 문제는 web.xml에 필터태그로 필터를 추가 등록하면서 bean등록이 2번 되었기 때문이다.

 

문제가 된 소스부분

@component 설정
web.xml에 filter 설정

 

둘 중 한개의 설정을 제거하고 한번만 정상적으로 동작하는것을 확인 하였다.

반응형
반응형

웹을 하다보면 자주 접하는 중복 로그인 방지 기능 요청사항이 들어오는데, HttpSessionListener를 통해 관리할 수 있습니다. 해당 객체는 Session이 생성되거나 제거될때 발생하는 이벤트를 제공하므로 등록만 해주면 세션을 통제할 수 있습니다.

 

HttpSessionListener

 

@WebListener
public class SessionConfig implements HttpSessionListener {

    @Override
    public void sessionCreated(HttpSessionEvent hse) {
		//세션 생성시
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent hse) {
		//세션 삭제시
    }
}

HttpSessionListener는 EventListener를 상속받아 구현되어 있고 sessionCreated와 sessionDestroyed를 상속받습니다.

 

메소드명 그대로 sessionCreated는 세션이 생성될 때 동작하며, sessionDestroyed는 세션이 삭제될 때 생성됩니다.

 

우리는 해당 리스너에서 전역으로 처리할 세션 컬렉션을 통해 관리를 할 예정입니다.

private static final Map<String, HttpSession> sessions = new ConcurrentHashMap<>();

ConcurrentHashMap을 사용하여 세션을 처리합니다.

ConcurrentHashMap는 일반 HashMap과는 다르게 key, value값으로 Null을 허용하지 않는 컬렉션입니다.

 

다음은 해당 리스너를 사용한 예제입니다.

 

사용 예제

 

SessionConfig.java

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;

@WebListener
public class SessionConfig implements HttpSessionListener {

	private static final Map<String, HttpSession> sessions = new ConcurrentHashMap<>();
	
	//중복로그인 지우기
	public synchronized static String getSessionidCheck(String type, String compareId){
		String result = "";
		for( String key : sessions.keySet() ){
			HttpSession hs = sessions.get(key);
			if(hs != null &&  hs.getAttribute(type) != null && hs.getAttribute(type).toString().equals(compareId) ){
				result =  key.toString();
			}
		}
		removeSessionForDoubleLogin(result);
		return result;
	}
	
	private static void removeSessionForDoubleLogin(String userId){    	
		System.out.println("remove userId : " + userId);
		if(userId != null && userId.length() > 0){
			sessions.get(userId).invalidate();
			sessions.remove(userId);    		
		}
	}
	
	@Override
	public void sessionCreated(HttpSessionEvent se) {
		System.out.println(se);
	    sessions.put(se.getSession().getId(), se.getSession());
	}
	
	@Override
	public void sessionDestroyed(HttpSessionEvent se) {
		if(sessions.get(se.getSession().getId()) != null){
			sessions.get(se.getSession().getId()).invalidate();
			sessions.remove(se.getSession().getId());	
		}
	}
}

SessionConfig는 @WebListener 어노테이션을 통해 리스너임을 명명합니다.

 

어노테이션 방식이 아닌 설정파일에 추가할 경우 web.xml에 listener태그를 통해 추가해주시면 됩니다.

@WebListener가 아닌 web.xml설정하기

<listener>
	<listener-class>패키지경로.SessionConfig</listener-class>
</listener>

getSessionCheck메소드에 synchronized키워드가 보이실 텐데, 모르는분들을 위하여 간단하게 설명하면 멀티쓰레드로 인한 동시 접근을 막아 처리의 순서를 보장하기위해 해당 키워드를 처리하였습니다. (톰캣은 접속하는 세션이 늘어날 때마다 쓰레드가 증가됩니다. 기본 개수는 200개였던것으로 기억합니다...)

 

 

login.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Session Test</title>
</head>
<body>
	<form action="/login.do" method="POST">
		id : <input type="text" id="id" name="id">
		<input type="submit" value="login">
	</form>
</body>
</html>

간단하게 ID만 받을 form태그입니다.

 

 

LoginController.java

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

@Controller
public class LoginController {
	
	@RequestMapping(value = "/login.do", method = RequestMethod.POST)
	public String login(HttpServletRequest request, HttpSession session, RedirectAttributes rttr) throws Exception {
		String id = request.getParameter("id");
		if(id != null){
			String userId = SessionConfig.getSessionidCheck("login_id", id);
			System.out.println(id + " : " +userId);
			session.setMaxInactiveInterval(60 * 60);
			session.setAttribute("login_id", id);
			return "redirect:/home.do";
		}
		return "redirect:/main.do";
	}
	
	@RequestMapping(value = "/main.do")
	public String index(HttpSession session) throws Exception {
		return "login";
	}
	
	@RequestMapping(value = "/home.do")
	public String home(HttpSession session) throws Exception {
		return "home";
	}
}

메인 페이지, 로그인 성공시 home.jsp로 처리할 매핑 함수와 로그인 처리를 할 함수를 구성한 로그인 컨트롤러입니다.

 

마지막으로 인터셉터를 구성 후 테스트를 진행해보겠습니다.

 

 

LoginInterceptor.java

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

public class LoginInterceptor extends HandlerInterceptorAdapter {
	
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
		final HttpSession session = request.getSession();
		String path = request.getRequestURI();
		if(path.contains("/main.do") || path.contains("/login.do")) { //접근 경로가 main.do인 경우에인 interceptor 체크 예외
			return true;
		}else if (session.getAttribute("login_id") == null) {  //세션 로그인이 없으면 리다이렉트 처리
			response.sendRedirect("/main.do");
			return false;
		}
		
		return true;
	}
}

main.do, login.do를 제외하고 세션의 login_id값이 존재하는지 체크 후 존재하지 않는다면 기본 페이지로 리다이렉트 처리를 해주는 인터셉터입니다.

인터셉터 사용을 위해 설정을 추가합니다.

 

 

servlet-context.xml

<mvc:interceptors>
	<mvc:interceptor>
		<mvc:mapping path="/*.do" />
		<beans:bean class="com.test.httpSessions.LoginInterceptor" />
	</mvc:interceptor>
</mvc:interceptors>

 

 

결과 테스트

 

테스트를 위해 파이어폭스에서 main.do를 접근하였습니다.

 

다음은 IE에서 추가로 접근하였습니다.

해당 서버에 접근하는 순간 세션이 생기면서 SessionConfig.sessionCreated에 sysout을 찍어놓은 부분이 동작하여 주소값이 출력되는 모습을 확인할 수 있습니다.

 

이제 로그인 테스트를 해보겠습니다. DB는 제외되었고 당연히 정상 입력이라고 가정하고 테스트를 진행합니다.

admin을 입력하여 로그인합니다.
정상 로그인되어 home.jsp가 출력됩니다.

 

 

다음은 IE에서 admin으로 로그인해보겠습니다.

정상 접속

 

역시 정상적으로 접속 되었고 파이어폭스에서 새로고침을 해보면 로그인 페이지로 이동된 것을 볼 수 있습니다.

기존에 접속되어있던 admin 중복 세션을 제거하였기 때문입니다.

/home.do는 세션을 체크하는 인터셉터에 의하여 초기페이지로 이동된 모습을 확인 할 수있습니다.

기존 로그인된 세션이 제거되어 로그인페이지로 변경

 

 

짤버전 추가...

중복로그인 체크

 

 

* 세션 중복제거를 하면서 헷갈렸던 부분은 SessionConfig의 sessionCreated메소드였는데, 당연히 session.setAttribute의 동작이 이루어지면 리스너에 의해서 이부분이 매번 동작되는것으로 착각하여 초기에 많은 시간의 뻘짓을 하였습니다. 죄 없는 이클립스가 캐시가 먹었다부터 해서 브라우저가 고장난건지 여러 의문을 품었지만 역시 컴퓨터는 거짓말을 하지 않습니다... 세션이 클라이언트가 해당 서버에 접근하는 순간 생성되는것이며, login_id의 관리는 별개로 컬렉션에서 관리하는것이므로 두 개념을 헷갈려서는 안됩니다...

반응형
반응형

체크박스나 라디오등을 제어하다보면 jQuery에 의존해서 많이 사용하게 되는데 순수 javascript만의 힘으로 제어하는 방법을 알아보겠습니다.

 

생각보다 사용법이 jQuery와 많이 다르지 않으며 비슷하기에 어렵지 않을 것입니다.

무엇보다도 추가적으로 라이브러리(jQuery)가 필요하지 않기에 빠르기도하고 간단하게 데이터를 확인할 수 있습니다.

 

 

체크박스의 체크 유무

먼저 체크박스값에 체크가 되어있는지 확인해보겠습니다.

.checked 를 통해 체크 유무를 검사할 수 있습니다.

 

html

<input type="checkbox" name="test1" value="test1">TEST1

 

js

var chk = document.querySelector("input[name=test1]").checked;
console.log(chk);

 

결과

체크가 해제되어있으면 false
체크되어 있다면 true

 


체크된 체크박스의 값 가져오기

이번에는 취미생활에 체크된 데이터의 value를 가져와 보겠습니다.

 

hobby.html

<form>
    <input type="checkbox" name="hobby" value="music">음악감상
    <input type="checkbox" name="hobby" value="game">게임
    <input type="checkbox" name="hobby" value="travel">여행
    <input type="checkbox" name="hobby" value="soccer">축구
    <input type="checkbox" name="hobby" value="reading">독서
    <input type="checkbox" name="hobby" value="cooking">요리
</form>

 

hobby.js

var chkList = document.querySelectorAll("input[name=hobby]:checked");
chkList.forEach(function (ch) {
    console.log(ch.value);
});

 

결과

querySelectorAll을 활용하여 name속성이 hobby인 데이터 중에 :checked속성이 있는 데이터만 추출하여 chkList에 담아두었습니다.

chkList를 forEach메소드를 통해 각각 요소마다 접근하여 value값을 console.log를 통해 출력하는 예제입니다.

 

해당부분을 특정 배열에 push하여 담아도 되고, 문자열에 붙여서 처리하면 될 것 같습니다.


모든 체크박스 선택하기

게시판이나 여러 형태를 작성하다보면 특정값이 모두 선택되게 해야하는 경우가 있습니다.

change 이벤트를 추가하여 제어해보겠습니다.

 

See the Pen vanillaJS CheckBox by myhappyman (@myhappyman) on CodePen.

결과

전체선택

hobbyAll의 요소를 선택하여 change 이벤트가 발생하게 되면

name값이 hobby인 데이터를 모두 찾아 속성값을 전체선택된 데이터값으로 변경처리를 해줍니다.

반응형