Knockout HTML Helper Editor

I thought it would be very useful to have an extended version of the EditorFor HTML helper, which automatically records value data bindings for Knockout JS.

It will look like this: a client-side view model and a server side view model - I have already autogenerated a client-side view model using ko matching and getting the viewmodel via AJAX.

Has anyone else tried something similar, or are there projects that include something similar to what I think here?

The advantage of this would be that during refactoring there would be no danger that data-related data would be missed.

+5
source share
2 answers

- , , , .

using System.Web.Mvc.Html;

namespace System.Web.Mvc
{
    public static class EditorForExtensions
    {
        public static MvcHtmlString TextBoxForViewModel<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression)
        {
            ModelMetadata metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);

            var htmlAttributes = HtmlAttributesForKnockout(metadata);

            return htmlHelper.TextBoxFor(expression, htmlAttributes);
        }

       private static Dictionary<string, object> HtmlAttributesForKnockout(ModelMetadata metadata)
        {
            var htmlAttributes = new Dictionary<string, object>();

            var knockoutParameter = String.Format("value: {0}", metadata.PropertyName);

            htmlAttributes.Add("data-bind", knockoutParameter);

            return htmlAttributes;
        }
    }
}

:

@Html.TextBoxForViewModel(m => m.Name)
+3

htmlAttributes , . . (, , !)

using System.Collections.Generic;
using System.Linq.Expressions;
using System.Web.Mvc.Html;

namespace System.Web.Mvc {
    public static class KnockoutExtensions {
        public static MvcHtmlString KnockoutTextBoxFor<TModel, TProperty>( this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression ) {
            var metadata = ModelMetadata.FromLambdaExpression( expression, htmlHelper.ViewData );
            var htmlAttributes = HtmlAttributesForKnockout( metadata );
            return htmlHelper.TextBoxFor( expression, htmlAttributes );
        }

        public static MvcHtmlString KnockoutTextBoxFor<TModel, TProperty>( this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object attributes ) {
            // convert passed anonymous object (attributes) into IDictionary<string,object> to pass into attribute parser
            var attrs = HtmlHelper.AnonymousObjectToHtmlAttributes( attributes ) as IDictionary<string, object>;
            var metadata = ModelMetadata.FromLambdaExpression( expression, htmlHelper.ViewData );

            var htmlAttributes = HtmlAttributesForKnockout( metadata, attrs );

            return htmlHelper.TextBoxFor( expression, htmlAttributes );
        }

        private static Dictionary<string, object> HtmlAttributesForKnockout( ModelMetadata metadata, IEnumerable<KeyValuePair<string, object>> attributes = null ) {
            var htmlAttributes = new Dictionary<string, object>();

            var knockoutParameter = String.Format( "value: {0}", metadata.PropertyName );
            htmlAttributes.Add( "data-bind", knockoutParameter );

            if ( attributes != null ) foreach ( var attr in attributes ) htmlAttributes.Add( attr.Key, attr.Value );

            return htmlAttributes;
        }
    }
}
+1

All Articles