ненавязчивая проверка клиента в привязке нокаут-шаблона - PullRequest
10 голосов
/ 05 февраля 2012

У меня есть модель с аннотациями данных, и я динамически связываю ее с viewmodel, использующей плагин привязки и привязки к шаблону.Я пытаюсь сделать ненавязчивую проверку клиента для моей модели.Как мы можем сделать это в этом сценарии.Любая помощь / предложения?

public class MyUser
    {
        [Required]
        [StringLength(35)]
        public string Username { get; set; }

        [Required]
        [StringLength(35)]
        public string Forename { get; set; }

        [Required]
        [StringLength(35)]
        public string Surname { get; set; }
    }

На мой взгляд, я динамически привязываю шаблон MyUser, используя ajax.

public JsonResult TestKnockout()
        {
            IList<MyUser> myUserList = new List<MyUser>();
            myUserList.Add(new MyUser { Username = "ajohn", Surname = "surname" });
            myUserList.Add(new MyUser { Username = "ajohn1", Surname = "surname1" });

            return Json(myUserList, JsonRequestBehavior.AllowGet);
        }
    }

Вид:

<form id="Userform" action='@Url.Action("Save", "Home")' data-bind="template: {name: 'UserTemplate', foreach:UserList}">
<input type="Submit" name="name" value="Submit" />
</form>
<script id="UserTemplate" type="text/Html">
 <input type="text" data-bind="value: Username"></input>
 <input type="text" data-bind="value: Forename"></input>
 <input type="text" data-bind="value: Surname"></input> 
</script>
<script type="text/javascript">


    var viewModel = {
        UserList: ko.observableArray(new Array()),

        Save: function () {          
            //// reached here means validation is done.
            alert("Save");
        }
    }
    ko.applyBindings(viewModel);


    $.ajax({
        type: 'GET',
        url: '../Home/TestKnockout',
        contentType: "application/json",
        success: function (data) {
            $.each(ko.mapping.fromJS(data)(), function () {
                viewModel.UserList.push(this);
            })

            // attach the jquery unobtrusive validator
            $.validator.unobtrusive.parse("#Userform");

            // bind the submit handler to unobtrusive validation.
            $("#Userform").data("validator").settings.submitHandler = viewModel.Save;
        },
        error: function (xhr, ajaxOptions, thrownError) {
            alert(xhr.status);
            alert(thrownError);
        }
    });

</script>

Ответы [ 4 ]

11 голосов
/ 21 апреля 2012

Pilavdzice и Drogon ответы довольно хороши, но мы забываем основную мысль.

Поскольку мы используем шаблон MVVM для разделения пользовательского интерфейса и данных (+ vm), мы не хотим выполнять проверку пользовательского интерфейса, но проверяем данные. Эти два совершенно разные, jquery validate - отличный плагин, но он выполняет валидацию UI (он запускается из UI для проверки полей).

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

К сожалению, если ваша viewmodel становится сложной, у этого плагина будут некоторые проблемы, но в любом случае это путь.

Проверка пользовательского интерфейса идеальна, если мы не используем шаблон MVVM, в конце концов, для чего мы разделяем компоненты (M-V-VM)?

Надеюсь, я помог!

Спасибо!

4 голосов
/ 19 апреля 2014

У меня была такая же проблема, как и у вас, поэтому я написал следующий компонент.

https://www.nuget.org/packages/ScriptAnnotations/

https://scriptannotations.codeplex.com/

Пожалуйста, дайте мне знать, если это поможет.

2 голосов
/ 10 марта 2012

Если вы используете knockoutjs и jquery, я придумал следующий очень простой метод для выполнения базовой проверки.

Везде, где вы хотите отобразить сообщение об ошибке на своей странице, добавьте тег span, как этот:

<span name="validationError" style="color:Red" 
data-bind="visible: yourValidationFunction(FieldNameToValidate())">
* Required.
</span>

Очевидно, что вам нужно написать «yourValidationFunction», чтобы делать то, что вы хотите. Он просто должен возвращать true или false, true означает, что отображается ошибка.

Вы можете использовать jquery для предотвращения продолжения работы пользователя, если отображаются какие-либо ошибки проверки. Возможно, у вас уже есть кнопка сохранения, которая запускает функцию javascript для выполнения какого-либо ajax или чего-то еще, поэтому просто добавьте это вверху:

 if ($("[name='validationError']:visible").length > 0) {
        alert('Please correct all errors before continuing.');
        return;
    }

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

2 голосов
/ 07 февраля 2012

Я бы пошел с привязкой события jquery для этого.

Сначала добавьте ваши атрибуты data-val к ​​входам, которые вы хотите проверить.(Чтобы выяснить, какие атрибуты data-val следует использовать, я обычно связываю сторону сервера формы с моделью и источником представления.)

     <input data-val-required="test" data-val="true" data-bind="visible: 
     $parent.userEditMode, value: FirstName" />

Во-вторых, добавьте функцию утилиты проверки - это вызывает jqueryплагин validation, используемый MVC под одеялом.

    function validateForm(thisForm) {
        var val = thisForm.validate();
        var isValid = val.form();
        alert(isValid);
        if (!isValid) {
            thisForm.find('.input-validation-error').first().focus();
        }
        return isValid;
    }

В-третьих, вызовите validate перед выдачей метода viewmodel.Обязательно удалите атрибут привязки данных click из разметки на вашей странице.

$('#..your form id...').live('submit', function (e) {
    e.preventDefault();
    if(validateForm($(this)))
        viewModel.saveUser();
});
...