Kendo Grid Редактировать сообщение InLine Custom Validation, например. для дубликатов имен и т.д.
У меня есть сущность Местоположение, и я использую сетку интерфейса Kendu UI с режимом редактирования InLine.
Объект имеет свойство DisplayName, которое требуется, и не должно существовать дважды в базе данных.
В настоящий момент он работает для отображения сообщения Обязательное:
![enter image description here]()
И он также работает над созданием метода CustomValidateModel, вызванного в методе LocationController " → Ajax InLine Create, который проверяет, существует ли Имя уже в базе данных и добавляет a ModelError. Я поймаю эту ошибку, а затем в .Events(events = > events.Error(" onError")) через javascript и покажу затем сообщение через всплывающее окно javascript.
ModelState.AddModelError("DisplayName", "Name already exists.");
![enter image description here]()
И в этом суть проблемы: Я не хочу иметь это всплывающее сообщение javascript. Я хочу также получить эту информацию под полем, например, "Поле обязательное!" сообщение.
Я искал много времени, но большинство людей предлагают только эту проверку и выводят через javascript, поскольку она работает в данный момент.
Кроме того, фактическая проблема, кроме всплывающего окна, заключается в том, что запись, которую пользователь хочет создать в Grid, затем исчезает после подтверждения всплывающего окна javascript.
Но для удобства использования я хочу, чтобы новая строка и вход сохранялись. Пользователи должны иметь возможность редактировать данное имя, он хотел сохранить. И НЕ должен снова войти в полную строку. Только сообщение "Имя уже существует". должен запрашивать информацию.
Код:
Объект местоположения:
public class LocationDto
{
public Guid? ID { get; set; }
[Required(AllowEmptyStrings = false, ErrorMessage = "Field required!")]
public string DisplayName { get; set; }
// other properties
}
LocationController Действие:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult CreateInline([DataSourceRequest] DataSourceRequest request, LocationDto model)
{
CustomValidateModel(model); // checks if the DisplayName is already existing in the DB
if (model != null && ModelState.IsValid)
{
// Create and Save the Model into database
}
return Json(ModelState.ToDataSourceResult());
}
Функция javascript:
function onError(e, status) {
if (e.errors) {
var message = "Error:\n";
$.each(e.errors, function (key, value) {
if (value.errors) {
message += value.errors.join("\n");
}
});
this.cancelChanges();
alert(message);
}
}
Я надеюсь, что есть возможность заставить это работать таким же образом. Это было бы прекрасно в соответствии с конгруэнтной визуализацией и улучшением удобства использования.
Ответы
Ответ 1
С изменением другого ответа и опробования я построил рабочее решение:
Местоположение Edit.cshtml Grid Razor:
.DataSource(ds => ds
.Ajax()
.Events(e => e.Error("onError"))
.Model(m =>
{
m.Id(e => e.ID);
...
})
.Create(create => create.Action("CreateInLine", "Location"))
.Read(...)
.Update(update => update.Action("UpdateInLine", "Location"))
.Destroy(...)
)
Местоположение Edit.cshtml js:
<script type="text/javascript">
function onError(e, status) {
if (e.errors) {
var message = "Error:\n";
var grid = $('#locationGrid').data('kendoGrid');
var gridElement = grid.editable.element;
var validationMessageTemplate = kendo.template(
"<div id='#=field#_validationMessage' " +
"class='k-widget k-tooltip k-tooltip-validation " +
"k-invalid-msg field-validation-error' " +
"style='margin: 0.5em;' data-for='#=field#' " +
"data-val-msg-for='#=field#' role='alert'>" +
"<span class='k-icon k-warning'></span>" +
"#=message#" +
"<div class='k-callout k-callout-n'></div>" +
"</div>");
$.each(e.errors, function (key, value) {
if (value.errors) {
gridElement.find("[data-valmsg-for=" + key + "],[data-val-msg-for=" + key + "]")
.replaceWith(validationMessageTemplate({ field: key, message: value.errors[0] }));
gridElement.find("input[name=" + key + "]").focus();
}
});
grid.one("dataBinding", function (e) {
e.preventDefault(); // cancel grid rebind
});
}
}
</script>
LocationController.cs
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult CreateInLine([DataSourceRequest] DataSourceRequest request, LocationViewModel model)
{
CustomValidateModel(model);
if (model != null && ModelState.IsValid)
{
var location = _repository.CreateNewInstance<Location>();
location.ID = Guid.NewGuid();
location.DisplayName = model.DisplayName;
...
_repository.SaveChanges();
model = MapToViewModel(location);
}
return Json(new[] { model }.ToDataSourceResult(request, ModelState));
}
private void CustomValidateModel(LocationViewModel model)
{
var existingEntity = _repository.GetAll<Location>()
.Where(o => o.ID != model.ID)
.Where(o => o.DisplayName.Equals(model.DisplayName))
.FirstOrDefault();
if (existingEntity != null)
{
if (existingEntity.Deleted == false)
ModelState.AddModelError("DisplayName", "Name already exists.");
else
ModelState.AddModelError("DisplayName", "Name '" + existingEntity.DisplayName + "' already exists in DB, but deleted.");
}
}
Результат:
![enter image description here]()
Ответ 2
Мы выполнили это в Grid так же, как вы сделали на стороне контроллера, добавив нашу пользовательскую ошибку в состояние модели и передав ее обратно в представление. А затем в событии onError javascript мы сами создали сообщение проверки и поместили его в сетку.
Javascript onError:
function onError(e, status) {
if (e.errors) {
var message = "Error:\n";
var grid = $('#gridID').data('kendoGrid');
var gridElement = grid.editable.element;
$.each(e.errors, function (key, value) {
if (value.errors) {
gridElement.find("[data-valmsg-for=" + key + "],[data-val-msg-for=" + key + "]")
.replaceWith(validationMessageTmpl({ field: key, message: value.errors[0] }));
gridElement.find("input[name=" + key + "]").focus()
}
});
}
}
Затем создайте validationMessageTmpl (или все, что вы хотите называть):
var validationMessageTmpl = kendo.template($("#message").html());
<script type="text/kendo-template" id="message">
<div class="k-widget k-tooltip k-tooltip-validation k-invalid-msg field-validation-error" style="margin: 0.5em; display: block; " data-for="#=field#" data-valmsg-for="#=field#" id="#=field#_validationMessage">
<span class="k-icon k-warning">
</span>
#=message#
<div class="k-callout k-callout-n">
</div>
</div>
</script>
Что касается того, почему пользовательский ввод исчезает, я предполагаю, что:
this.cancelChanges();
может иметь какое-то отношение к этому. Я считаю, что это делает то, что он говорит, и отменяет все изменения. Что бы reset ваша сетка и удалить все пользовательские ввод.
Следует отметить: Код в ModelState (также ключевой элемент вашего $.each) должен быть тем же именем, что и свойство модели представления, которое используется для столбца, который вы хотите отобразить ошибка.
Ответ 3
Вы можете попробовать это:
DisplayName: {
validation: {
required: true,
DisplayNameValidation: function (input) {
var exists = CheckName(input.val());
if (exists && input.is("[name='DisplayName']") && input.val() != "") {
input.attr("data-DisplayNameValidation-msg", "Name already exists.");
return false;
}
}
return true;
}
}
И
function CheckName(Name) {
var exists = false;
$.ajax
({
type: "POST",
url: "CheckName",
data: "{Name:'" + Name + "'}",
contentType: "application/json; charset=utf-8",
dataType: "json",
async: false,
error: function (msg) {
},
success: function (response) {
exists = response;
}
});
return exists;
}
Для дополнительной документации проверьте демонстрационный сайт kendo для пользовательской проверки.