using System; using System.Collections.Generic; using System.Linq.Expressions; using System.Web; using System.Web.Mvc; using HtmlTags; using Humanizer; using InventoryTraker.Web.Utilities; namespace InventoryTraker.Web.Helpers { public class AngularModelHelper { protected readonly HtmlHelper Helper; private readonly string _expressionPrefix; public AngularModelHelper(HtmlHelper helper, string expressionPrefix) { Helper = helper; _expressionPrefix = expressionPrefix; } /// /// Converts an lambda expression into a camel-cased string, prefixed /// with the helper's configured prefix expression, ie: /// vm.model.parentProperty.childProperty /// public IHtmlString ExpressionFor(Expression> property) { var expressionText = ExpressionForInternal(property); return new MvcHtmlString(expressionText); } /// /// Converts a lambda expression into a camel-cased AngularJS binding expression, ie: /// {{vm.model.parentProperty.childProperty}} /// public IHtmlString BindingFor(Expression> property) { return MvcHtmlString.Create("{{" + ExpressionForInternal(property) + "}}"); } /// /// Creates a div with an ng-repeat directive to enumerate the specified property, /// and returns a new helper you can use for strongly-typed bindings on the items /// in the enumerable property. /// public AngularNgRepeatHelper Repeat( Expression>> property, string variableName) { var propertyExpression = ExpressionForInternal(property); return new AngularNgRepeatHelper( Helper, variableName, propertyExpression); } private string ExpressionForInternal(Expression> property) { var camelCaseName = property.ToCamelCaseName(); var expression = !string.IsNullOrEmpty(_expressionPrefix) ? _expressionPrefix + "." + camelCaseName : camelCaseName; return expression; } public HtmlTag FormGroupFor(Expression> property) { var metadata = ModelMetadata.FromLambdaExpression(property, new ViewDataDictionary()); var name = ExpressionHelper.GetExpressionText(property); var expression = ExpressionForInternal(property); //Creates
var formGroup = new HtmlTag("div") .AddClasses("form-group", "has-feedback") .Attr("form-group-validation", name); var labelText = metadata.DisplayName ?? name.Humanize(LetterCasing.Title); //Creates var label = new HtmlTag("label") .AddClass("control-label") .Attr("for", name) .Text(labelText); var tagName = metadata.DataTypeName == "MultilineText" ? "textarea" : "input"; var placeholder = metadata.Watermark ?? (labelText + "..."); //Creates var input = new HtmlTag(tagName) .AddClass("form-control") .Attr("ng-model", expression) .Attr("name", name) .Attr("type", "text") .Attr("placeholder", placeholder); ApplyValidationToInput(input, metadata); return formGroup .Append(label) .Append(input); } private void ApplyValidationToInput(HtmlTag input, ModelMetadata metadata) { if (metadata.IsRequired) input.Attr("required", ""); if (metadata.DataTypeName == "EmailAddress") input.Attr("type", "email"); if (metadata.ModelType == typeof(DateTime)) input.Attr("type", "date"); if (metadata.DataTypeName == "PhoneNumber") input.Attr("pattern", @"[\ 0-9()-]+"); } } }