3. XE3.0 을 만들 때 이런 생각을 했습니다.
javascript form validation .. 귀찮다!!!
Backend 에서 처리하는 Validation 이 있는데 Javascript 에서도 또 만들어야 하나..
Backend 에서 사용한 Validation Rule 을 Frontend 에서 사용할 수 있게 해보자!
Frontend Validator
5. data-rule
하나의 페이지에서 여러개의 validation rule 사용
data-rule 로 사용할 frontend validator 이름 설정
개요 <form action="action_url" method="post" data-rule="join" data-rule-alert-type="custom_alert_type">
data-rule-alert-type
경고 메시지 처리 방법 설정
기본으로 toast, form 두가지 타입 제공
사용자는 별도의 메시지 처리 방식 사용할 수 있음
6. data-rule
<script type="text/javascript">
var ruleSet = { ruleName: "join", rules:
{"email":"required|email","display_name":"required","password":"required|confi
rmed|password","agree_termsofservice":"accepted","agree_private_info_colle
ct":"accepted"} };
</script>
하나의 페이지에서 여러개의 validation rule 사용
data-rule 로 사용할 frontend validator 이름 설정
<form action="action_url" method="post" data-rule="join"
data-rule-alert-type="custom_alert_type">
7. toast 사용
data-rule-alert-type
<form action="action_url" method="post" data-rule="join"
data-rule-alert-type="toast">
<form action="action_url" method="post" data-rule="join"
data-rule-alert-type="custom_alert_type">
custom alert type 사용
9. 동작
1. XeFrontend::rule() 로 form 에서 사용할 validation rule set 정의
2. form 에 data-rule 로 validation rule set 이름 지정
3. $('body').on('submit', 'form[data-rule]', ...) 으로 form 전송할 때 validation 실행
{{ XeFrontend::rule('join', [
"email" => "required|email"
"display_name" => "required"
"password" => "required|confirmed|password"
"agree_termsofservice" => "accepted"
"agree_private_info_collect" => "accepted"
]) }}
사용할 validation 정의
XeFrontend::rule 에서 지정한 첫번째 인자값 사용
data-rule="join"
data-rule 지정
form submit 이벤트 발생하면 validation 실행
javascript validator 사용
실패할 경우 griper 로 메시지 출력
form submit
10. <form action="action_url" method="post" data-rule="join" data-rule-alert-type="custom_alert_type">
...
</form>
<script>
var ruleSet = { ruleName: "join", rules:
{"email":"required|email","display_name":"required","password":"required|confirmed|password","agree_termsofservice":"accepted","agre
e_private_info_collect":"accepted"} }
</script>
<script>
$(function() {
XE.Validator.rules.join.password_confirmation = 'password_confirmation';
});
</script>
사용할 validation 정의
1. validator 가 ruleSet 변수에 할당된 json 데이터를 기반으로 처리
2. ruleSet 변수 할당은 {{ XeFrontend::rule($array) }} 로 처리
3. validator
https://github.com/xpressengine/xpressengine/blob/master/resources/assets/core/validator/index.js#L508
{{ XeFrontend::rule('join', [
"email" => "required|email"
"display_name" => "required"
"password" => "required|confirmed|password"
"agree_termsofservice" => "accepted"
"agree_private_info_collect" => "accepted"
]) }}
HTML
PHP
11. <form action="action_url" method="post" data-rule="join" data-rule-alert-type="custom_alert_type">
...
</form>
<script>
var ruleSet = { ruleName: "join", rules:
{"email":"required|email","display_name":"required","password":"required|confirmed|password","agree_termsofservice":"accepted","agre
e_private_info_collect":"accepted"} }
</script>
<script>
$(function() {
XE.Validator.rules.join.password_confirmation = 'password_confirmation';
});
</script>
validator evaluator
1. Backend(PHP) 에 구현된 rule 코드를 Frontend validator 에 구현
2. rule 에 대한 처리 코드
https://github.com/xpressengine/xpressengine/blob/master/resources/assets/core/validator/index.js#L54
required: function ($dst, parameters) {
const value = that.getValue($dst)
if (value === '') {
let errorMessage = 'validation.required'
if ($dst.is('input[type=checkbox]') ||
$dst.is('input[type=radio]')) {
errorMessage = 'validation.required_check'
} else if ($dst.is('input[type=select]')) {
errorMessage = 'validation.required_select'
}
that.error($dst, langInstance.trans(errorMessage, { attribute:
$dst.data('valid-name') || $dst.attr('name') }))
return false
}
return true
},
HTML
JAVASCRIPT
12. <form action="action_url" method="post" data-rule="join" data-rule-alert-type="custom_alert_type">
...
</form>
<script>
var ruleSet = { ruleName: "join", rules:
{"email":"required|email","display_name":"required","password":"required|confirmed|password","agree_termsofservice":"accepted","agre
e_private_info_collect":"accepted"} }
</script>
<script>
$(function() {
XE.Validator.rules.join.password_confirmation = 'password_confirmation';
});
</script>
validator custom rule
1. 코어에서 지원하지 않는 password_confirmation 처리
추가 rule 지정, XE.Validator.put()
https://github.com/xpressengine/xpressengine/blob/master/resources/assets/core/validator/index.js#L736
2. 추가한 rule 을 form 에 연결
join 으로 정의한 validation 에 추가한 password_confirmation 연결
XE.Validator.put('password_confirmation', function ($dst,
parameters) {
if ($dst.val() == '') {
XE.Validator.error($dst, "비밀번호를 한번 더 입력해주세요
.");
return false;
}
var password = $('[name="password"]').val();
if ($dst.val() != password) {
XE.Validator.error($dst, "비밀번호가 일치하지 않습니다.");
return false;
}
return true;
});
JAVASCRIPTHTML
13. griper
1. griper
사용자 메시지 출력
toast, form 두가지 방식으로 메시지 처리
2. validator evaluator 가 실패할 경우 메시지 처리
XE.validator.error() 가 griper 사용해서 메시지 처리
https://github.com/xpressengine/xpressengine/blob/master/resources/assets/core/validator/i
ndex.js#L786
3. XE.validator.extendAlertType() 으로 메시지 처리 방식 추가
var custom_alert_type = {
constructor: this,
options: {
selectors: {elementGroup: '.form-group', errorText: '.__xe_error_text'},
classes: {message: ['error-text', '__xe_error_text', 'text_caution']},
tags: {message: 'p'}
},
getGroup: function ($element) {
return $element.closest(this.options.selectors.elementGroup)
},
putByElement: function ($element, message) {
this.put(this.getGroup($element), message, $element)
},
put: function ($group, message, $element) { ... },
clear: function ($form) {
$form.find(this.options.tags.message + this.options.selectors.errorText).remove()
}
};
XE.Validator.extendAlertType('custom_alert_type', function ($element, message) {
custom_alert_type.putByElement($element, message);
});
JAVASCRIPT
14. 메시지 출력 대상 이름 지정
1. 입력 상자 이름 지정
"이메일" 이름을 지정할 때 대상을 지정할 방법 필요
<form action="action_url" method="post" data-rule="join" data-rule-alert-type="custom_alert_type">
...
<input type="text" name="email" id="email" title="이메일" placeholder="이메일:예)hello@homespace.co.kr"
class="inp_apply_common" value="" data-valid-name="이메일">
...
</form>
HTML
15. translator
1. XE 는 다국어 지원
메시지 처리할 때 다국어 지원
https://github.com/xpressengine/xpressengine/blob/master/resources/ass
ets/core/validator/index.js#L97
2. 메시지 출력할 때 message key 사용
validation.required 와 같이 메시지를 직접 사용하지 않고 message key 로
지정
Backend 에서 정의된 메시지
https://github.com/xpressengine/xpressengine/blob/master/resources/lan
g/ko/validation.php
https://github.com/xpressengine/xpressengine/blob/master/resources/lan
g/common.php
required: function ($dst, parameters) {
const value = that.getValue($dst)
if (value === '') {
let errorMessage = 'validation.required'
if ($dst.is('input[type=checkbox]') ||
$dst.is('input[type=radio]')) {
errorMessage = 'validation.required_check'
} else if ($dst.is('input[type=select]')) {
errorMessage = 'validation.required_select'
}
that.error($dst, langInstance.trans(errorMessage, { attribute:
$dst.data('valid-name') || $dst.attr('name') }))
return false
}
return true
},
JAVASCRIPT