Files
InventoryTraker-Box/InventoryTraker.Web/Helpers/AngularModelHelper.cs
T
poprhythm a5fcb46e04 InventoryType from XML
Transaction updates
2016-08-25 13:00:09 -04:00

133 lines
3.9 KiB
C#

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<TModel>
{
protected readonly HtmlHelper Helper;
private readonly string _expressionPrefix;
public AngularModelHelper(HtmlHelper helper, string expressionPrefix)
{
Helper = helper;
_expressionPrefix = expressionPrefix;
}
/// <summary>
/// Converts an lambda expression into a camel-cased string, prefixed
/// with the helper's configured prefix expression, ie:
/// vm.model.parentProperty.childProperty
/// </summary>
public IHtmlString ExpressionFor<TProp>(Expression<Func<TModel, TProp>> property)
{
var expressionText = ExpressionForInternal(property);
return new MvcHtmlString(expressionText);
}
/// <summary>
/// Converts a lambda expression into a camel-cased AngularJS binding expression, ie:
/// {{vm.model.parentProperty.childProperty}}
/// </summary>
public IHtmlString BindingFor<TProp>(Expression<Func<TModel, TProp>> property, string filter = "")
{
return MvcHtmlString.Create("{{"
+ ExpressionForInternal(property)
+ (!string.IsNullOrEmpty(filter) ? " | " + filter : string.Empty)
+ "}}");
}
/// <summary>
/// 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.
/// </summary>
public AngularNgRepeatHelper<TSubModel> Repeat<TSubModel>(
Expression<Func<TModel, IEnumerable<TSubModel>>> property, string variableName)
{
var propertyExpression = ExpressionForInternal(property);
return new AngularNgRepeatHelper<TSubModel>(
Helper, variableName, propertyExpression);
}
private string ExpressionForInternal<TProp>(Expression<Func<TModel, TProp>> property)
{
var camelCaseName = property.ToCamelCaseName();
var expression = !string.IsNullOrEmpty(_expressionPrefix)
? _expressionPrefix + "." + camelCaseName
: camelCaseName;
return expression;
}
public HtmlTag FormGroupFor<TProp>(Expression<Func<TModel, TProp>> property)
{
var metadata = ModelMetadata.FromLambdaExpression(property, new ViewDataDictionary<TModel>());
var name = ExpressionHelper.GetExpressionText(property);
var expression = ExpressionForInternal(property);
//Creates <div class="form-group has-feedback"
// form-group-validation="Name">
var formGroup = new HtmlTag("div")
.AddClasses("form-group", "has-feedback")
.Attr("form-group-validation", name);
var labelText = metadata.DisplayName ?? name.Humanize(LetterCasing.Title);
//Creates <label class="control-label" for="Name">Name</label>
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 <input ng-model="expression"
// class="form-control" name="Name" type="text" >
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");
input.Attr("bs-datepicker");
input.Attr("data-date-format", "M/d/yyyy");
}
if (metadata.DataTypeName == "PhoneNumber")
input.Attr("pattern", @"[\ 0-9()-]+");
}
}
}