Сообщение Kendo Grid Edit InLine Custom Validation, например. для повторяющихся имен и т. д.

У меня есть объект Location, и я использую сетку пользовательского интерфейса Kendu с режимом редактирования InLine. Сущность владеет свойством DisplayName, которое является обязательным и не должно существовать дважды в базе данных.

На данный момент работает отображение сообщения Required Validation: введите описание изображения здесь

И он также работает для создания метода CustomValidateModel, вызываемого в методе LocationController Ajax InLine Create, который проверяет, существует ли имя в базе данных, и затем добавляет МодельОшибка. Затем я ловлю эту ошибку в .Events(events => events.Error("onError")) через javascript и затем показываю сообщение через всплывающее окно javascript.

ModelState.AddModelError("DisplayName", "Name already exists.");

введите здесь описание изображения

И вот в чем суть: Я не хочу, чтобы это всплывающее сообщение javascript. Я хочу также иметь эту информацию под полем, например «Поле обязательно!» сообщение. Я искал много времени, но большинство людей предлагают только эту проверку и вывод через javascript, поскольку он работает в данный момент.

Кроме того, фактическая проблема, помимо всплывающего окна, заключается в том, что запись, которую пользователь хочет создать в сетке, затем исчезает после подтверждения всплывающего окна 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);
    }
}

Я надеюсь, что есть возможность заставить это работать таким же образом. Было бы хорошо, если бы была конгруэнтная визуализация и повышение удобства использования.


person florian.isopp    schedule 09.07.2013    source источник


Ответы (3)


Мы выполнили это в сетке так же, как вы сделали на стороне контроллера, добавив нашу пользовательскую ошибку в состояние модели и передав ее обратно в представление. А затем в javascript-событии onError мы сами создали проверочное сообщение и поместили его в сетку.

Javascript при ошибке:

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();

может иметь к этому какое-то отношение. Я считаю, что это делает именно то, что говорит, и отменяет все изменения. Что сбросит вашу сетку и удалит все пользовательские данные.

Обратите внимание: код в ModelState (также ключ в вашем $.each) должен иметь то же имя, что и свойство модели представления, используемое для столбца, в котором вы хотите отобразить ошибку.

person larrydice    schedule 29.07.2013
comment
Хорошая отправная точка, но блок ‹script› построен некорректно, а сетка ложно сброшена. - person florian.isopp; 09.09.2013
comment
шаблон кендо лучше чем html разметка в строковой переменной как в предыдущем посте - person SerjG; 30.01.2015
comment
Также вот хороший трюк, как сделать обработчик более универсальным: .gridId).getKendoGrid(); - person SerjG; 30.01.2015
comment
Я считаю, что вам также нужно добавить grid.one(dataBinding, function (e) { e.preventDefault(); }); Если эта часть отсутствует, сообщение исчезнет, ​​например, во всплывающем окне. - person Mateusz Migała; 31.03.2016

Изменив другой ответ и попробовав, я построил рабочее решение:

Местоположение 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.");
        }
    }

Результат:

введите здесь описание изображения

person florian.isopp    schedule 09.09.2013
comment
Я предлагаю вам использовать шаблон кендо, как в следующем ответе. - person SerjG; 30.01.2015
comment
Также вот хороший трюк, как сделать обработчик более универсальным: .gridId).getKendoGrid(); - person SerjG; 30.01.2015
comment
удалить класс «k-invalid-msg» из validationMessageTemplate ==> это добавить css «display: none» - person habiat; 18.04.2015

Вы можете попробовать это;

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;

}

Для получения дополнительной документации посетите демонстрационный сайт кендо для пользовательской проверки.

person Mahib    schedule 24.05.2015