Каков наилучший способ проверки на стороне клиента с использованием Javascript (с минимальным дублированием кода) при использовании проверки JSR 303 bean на стороне сервера? В настоящее время я использую Spring 3, а Hibernate Validator.
JSR 303 Bean Валидация + Проверка на стороне клиента Javascript
Ответ 1
Я бы предположил, что вы смотрите на Spring JS, который сильно зависит от Dojo. Учебник можно найти здесь.
Самый простой способ начать играть с ним - загрузить Spring Roo, создать приложение для примера с пиклинками с одним из примеров - скрипты (это займет у вас 5 минут), а затем поиграйте с тем, как интегрируется javascript. Spring Roo создает приложение с тем же стеком технологий, который вы используете (Spring + hibernate + реализация jsr 303)
Ответ 2
Я нашел этот проект с открытым исходным кодом, но он выглядит мертвым, возможно, стоит воскресить.
http://kenai.com/projects/jsr303js/pages/Home
Эта библиотека обеспечивает проверку на стороне клиента формы HTML на основе аннотаций JSR-303 и Hibernate Validator, интегрированных с Spring MVC. Библиотека предоставляет базу кода проверки JavaScript, которая обрабатывает базовое взаимодействие с форматами HTML, а также функции JavaScript, реализующие аннотации проверки, поддерживаемые Hibernate Validator (в том числе не из спецификации JSR-303). Эта база кода JavaScript может быть включена в страницу с помощью предоставленного taglib или путем извлечения файла JavaScript из банки и включения его с помощью тега. После того, как эта база кода была включена в страницу, второй taglib используется для генерации кода JavaScript для проверки формы HTML. Вы также можете предоставить объект JSON в теге тега, чтобы указать дополнительную информацию о конфигурации.
Ответ 3
Вот как я это делаю, используя Spring MVC + JQuery + Bootstrap, частично на основе a последнее сообщение в блоге на SpringSource:
AddressController.java
@RequestMapping(value="/validate")
public @ResponseBody ValidationResponse processForm(Model model, @Valid AddressForm addressForm, BindingResult result) {
ValidationResponse res = new ValidationResponse();
if (result.hasErrors()) {
res.setStatus("FAIL");
for (ObjectError error : result.getAllErrors()) {
if (error instanceof FieldError) {
FieldError fieldError = (FieldError) error;
res.addError(fieldError.getField(), fieldError.getDefaultMessage());
}
}
}
else {
res.setStatus("SUCCESS");
}
return res;
}
AddressForm.java
public class AddressForm {
@NotNull
@Size(min=1, max=50, message="Address 1 is required and cannot be longer than {max} characters")
private String address1;
@Size(max=50, message="Address 2 cannot be longer than {max} characters")
private String address2;
// etc
}
ValidationResponse.java:
public class ValidationResponse {
private String status;
private Map<String,String> errors;
// getters, setters
}
address.jsp:
<f:form commandName="addressForm">
<div class="control-group">
<label for="address1">Address 1</label>
<div class="controls">
<f:input path="address1" type="text" placeholder="Placeholder Address 1" class="wpa-valid" />
<span class="help-inline"></span>
</div>
</div>
<!-- etc -->
<div class="form-actions">
<button type="submit" class="btn btn-primary">Save</button>
<button type="button" class="btn">Cancel</button>
</div>
</f:form>
<script type="text/javascript">
function collectFormData($fields) {
var data = {};
for (var i = 0; i < $fields.length; i++) {
var item = $($fields[i]);
data[item.attr("id")] = item.val();
}
return data;
}
function clearErrors($fields) {
for (var i = 0; i < $fields.length; i++) {
var item = $($fields[i]);
$("#"+item.attr("id")).parents(".control-group").removeClass("error");
$("#"+item.attr("id")).siblings(".help-inline").html("");
}
}
function markErrors(errors) {
$.each(errors, function(key, val) {
$("#"+key).parents(".control-group").addClass("error");
$("#"+key).siblings(".help-inline").html(val);
});
}
$(document).ready(function() {
var $form = $("form.validate");
$form.bind("submit", function(e) {
var $fields = $form.find(".validate");
clearErrors($fields);
var data = collectFormData($fields);
var validationUrl = "validate";
$.get(validationUrl, data, function(response) {
$("#alert").removeClass();
if (response.status == "FAIL") {
markErrors(response.errors);
$("#alert").addClass("alert alert-error");
$("#alert").html("Correct the errors below and resubmit.");
} else {
$("#alert").addClass("alert alert-success");
$("#alert").html("Success!");
$form.unbind("submit");
$form.submit();
}
}, "json");
e.preventDefault();
return false;
});
});
</script>
Он может использовать некоторый рефакторинг, но это сделает ajax GET с данными формы и обновит страницу на основе результата.
Ответ 4
Richfaces поддерживает это. У них есть небольшая демонстрация на их сайте.
Ответ 5
PrimeFaces Client Side Validation Framework поддерживает Bean проверку.
Ответ 6
Вот альтернатива с открытым исходным кодом для JSR-303.
Это решение может выполнять всю проверку сообщения запроса, но не требуется кодирование с ошибками.
https://github.com/ckpoint/CheckPoint
С контрольной точкой вся проверка возможна без дальнейшего кода, просто путем изменения аннотации метода контроллера.
После этого все параметры проверки могут быть легко сделаны на странице администратора.
Я думаю, что это видео поможет вам понять. https://youtu.be/I1aEIztXlhE
Ответ 7
Редактировать:
Действительно, JSR 303 - лучший способ (IMO) для проверки валидации на стороне клиента. Лучше всего, что если у вас есть собственные библиотеки js на фронте, вы можете использовать ту же проверку (тот же код) на сервере (если вы будете использовать node.js). Я создал библиотеку @stopopa/validation для этих целей. Я проверяю такие формы (In React.js):
import React, { Component } from "react";
import ReactDOM from "react-dom";
import validator, {
Collection,
Required,
Optional,
NotBlank,
Length,
Email,
} from "@stopsopa/validator";
class App extends Component {
constructor(...args) {
super(...args);
this.state = {
data: {
name: "",
email: ""
},
errors: {},
validate: false
};
}
onSubmit = async e => {
e.preventDefault();
const errors = await validator(this.state.data, new Collection({
name: new Required([
new NotBlank(),
new Length({min: 3}),
]),
email: new Required([
new NotBlank(),
new Email(),
])
}));
this.setState({
errors: errors.getFlat(),
validate: true,
});
if ( ! errors.count()) {
console.log('send data to server', this.state.data);
}
};
onChange = (name, value) => {
this.setState(state => ({
...state,
data: { ...state.data, ...{ [name]: value } }
}));
};
render() {
const s = this.state;
return (
<form onSubmit={this.onSubmit}>
<label>
name:
<input
value={s.data.name}
onChange={e => this.onChange("name", e.target.value)}
/>
</label>
{s.validate && s.errors.name && (
<div className="error">{s.errors.name}</div>
)}
<br />
<label>
email:
<input
value={s.data.email}
onChange={e => this.onChange("email", e.target.value)}
/>
</label>
{s.validate && s.errors.email && (
<div className="error">{s.errors.email}</div>
)}
<br />
<input type="submit" value="submit" />
</form>
);
}
}
ReactDOM.render(<App />, document.getElementById("root"));
живой пример доступен здесь: https://codesandbox.io/s/ymwky9603j