AndreyAkinshin / knockout-mvc

Power of Knockout.js for ASP.NET MVC
http://knockoutmvc.com
203 stars 125 forks source link

Unobtrusive Validation #23

Closed DR9885 closed 1 year ago

DR9885 commented 11 years ago

It would be nice if this bound to Unobtrusive validation easy... Which I was able to add pretty easy off the base htmlHelper.

public static class KnockoutEditorExtensions
    {
        public static MvcHtmlString KnockoutTextBoxFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression, string binding)
        {
            return html.TextBoxFor(expression, null, new { @data_bind = binding + ", attr: { 'name': '" + html.NameFor(expression) + "_' + $index() }" });
        }

        public static MvcHtmlString KnockoutValidationMessageFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression)
        {
            return html.ValidationMessageFor(expression, null, new { @data_bind = "attr: { 'data-valmsg-for': '" + html.NameFor(expression) + "_' + $index() }" });
        }
    }

NODE: Some of the code is referenced from here https://github.com/tathamoddie/KnockoutJS-Demos/issues

DonHartman commented 11 years ago

I ran into the same problem, and wrote up my own workaround extending ko. This way you can call other useful things off the KnockoutTagBuilder (eg. valueUpdate, Click, etc), and still have the validation.

The only issue I stumbled upon was having to pass in the HtmlHelper to get what I needed.

Alternatively, you could add the KnockoutContext to the ViewData, and write the same method as an Html extension, but it might feel a little odd getting a KnockoutTagBuilder back from an HtmlHelper method.

What I did:

        public static KnockoutTagBuilder<TModel> KnockoutTextBoxFor<TModel>(this KnockoutContext<TModel> ko, HtmlHelper<TModel> html, Expression<Func<TModel, object>> expression, object htmlAttributes) where TModel : class
        {
            KnockoutTagBuilder<TModel> tag = ko.Html.TextBox(expression, htmlAttributes);
            string propName = ExpressionHelper.GetExpressionText(expression);
            IDictionary<string, object> validationAttrs = html.GetUnobtrusiveValidationAttributes(propName, ModelMetadata.FromLambdaExpression(expression, html.ViewData));
            validationAttrs.Add("name", propName);
            tag.ApplyAttributes(validationAttrs);
            return tag;
        }

Any ideas on how to improve it?