敲除模板绑定中的非侵入式客户端验证

unobtrusive client validation in knockout template binding

提问人:HashCoder 提问时间:2/5/2012 更新时间:4/19/2014 访问量:8979

问:

我有一个带有数据注释的模型,我是一个动态绑定,使用敲除模板绑定和映射插件的视图模型。我正在尝试在我的模型上进行不显眼的客户端验证。在这种情况下,我们如何做到这一点。有任何帮助/建议吗?

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>
数据注释 敲除.js 不显眼的javascript 不显眼的验证 敲除映射插件

评论


答:

2赞 drogon 2/7/2012 #1

为此,我会使用 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();
});
2赞 pilavdzice 3/10/2012 #2

如果您使用的是 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;
    }

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

11赞 George Mavritsakis 4/21/2012 #3

Pilavdzice 和 Drogon 的答案相当不错,但我们忘记了基本点。

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

我发现淘汰验证插件似乎做得很好,它所做的是走相反的道路,它验证您的视图模型而不是您的 UI(它实际上映射到 UI 元素以显示错误)。

不幸的是,如果你的视图模型变得复杂,该插件将会出现一些问题,但无论如何,这是要走的路。

只要我们不使用 MVVM 模式,UI 验证就是完美的,毕竟我们分离组件 (M-V-VM) 是为了什么?

希望我能帮到我!

谢谢!

评论

3赞 afr0 2/17/2013
嗨,我只是在探索 KnockoutValidation 插件,我只是想知道它是否支持开箱即用的服务器端数据注释??或者是否需要在客户端 ViewModel 上实现所有验证。谢谢?
0赞 ZenMaster 10/16/2013
顺便说一句 - 我认为评论@pilavdzice的第一部分非常接近这一点 - 它依赖于 ViewModel 中的方法来提供数据验证的结果。
0赞 George Mavritsakis 10/16/2013
是的,它更接近于模型验证,但另一方面,该解决方案依赖于调用特定函数的 UI 来验证模型的元素。这意味着 model 和 ui 是耦合的。最好的解决方案是让模型自动验证,而 ui 只处理/显示验证结果。
1赞 George Mavritsakis 10/16/2013
此外,另一个关于敲除验证的项目是 knockoutvalidator.codeplex.com 这是我处理包括数组元素在内的模型验证的尝试。
4赞 Jason Bowers 4/19/2014 #4

我和你有同样的问题,所以我写了以下组件。

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

https://scriptannotations.codeplex.com/

如果有帮助,请告诉我。

评论

0赞 jbl 6/24/2014
这似乎很有趣。我去看看