在敲除模板绑定中不显眼的客户端验证

时间:2012-02-05 07:47:45

标签: data-annotations knockout.js unobtrusive-javascript unobtrusive-validation knockout-mapping-plugin

我有一个带有数据注释的模型,我是一个使用knockout模板绑定和映射插件的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; }
    }

在我看来,我使用ajax动态模板绑定MyUser列表。

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 个答案:

答案 0 :(得分:11)

pilavdzice和drogon的答案非常好,但我们忘记了基本点。

由于我们使用MVVM模式来分离UI和数据(+ vm),因此我们不想执行UI验证,而是使用DATA VALIDATION。这两个是完全不同的,jquery validate是一个很棒的插件,但它进行了UI验证(它从UI开始检查字段)。

我发现knockout validation plugin似乎做得很好,它做的是走相反的道路,它验证你的viewmodel而不是你的UI(它实际上映射到UI元素以显示错误)。< / p>

不幸的是,如果你的viewmodel变得复杂,那个插件会有一些问题,但无论如何这都是要走的路。

只要我们不使用MVVM模式,UI验证是完美的,毕竟我们将组件(M-V-VM)分开了吗?

希望我帮忙!

谢谢!

答案 1 :(得分:4)

我遇到了和你一样的问题所以我编写了以下组件。

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

https://scriptannotations.codeplex.com/

如果有帮助,请告诉我。

答案 2 :(得分:2)

我会选择jquery的事件绑定。

首先,将data-val属性添加到要验证的输入中。 (为了确定要使用哪些data-val属性,我通常将表单服务器端绑定到模型和视图源。)

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

其次,添加验证实用程序函数 - 这将调用MVC使用的jquery验证插件。

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

第三,在发出viewmodel方法之前调用validate。确保从页面中的标记中删除“click”数据绑定属性。

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

答案 3 :(得分:2)

如果您正在使用knockoutjs和jquery,我想出了以下非常简单的基本验证方法。

无论您希望在网页上显示错误消息,请在其中加入以下标记:

<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;
    }

这比许多其他验证解决方案更简单,更灵活。您可以将错误消息放在任何位置,也不需要学习如何使用某些验证库。