MVC3, Razor, Html.TextAreaFor (): adjust height to fit content

I am currently using the following code in a view to adjust the height of Html.TextAreaFor () to match its contents. Is there a significantly better and / or less detailed way to do this?

...
int width = 85;
int lines = 1;
string[] arr = Model.Text.Split(new string[] {"\r\n", "\n", "\r"}, StringSplitOptions.None);
foreach (var str in arr)
{
    if (str.Length / width > 0)
    {
        lines += str.Length / width + (str.Length % width <= width/2 ? 1 : 0);
    }
    else
    {
        lines++;
    }
}
@Html.TextAreaFor(m => m.Text,
                  new
                  {
                      id = "text",
                      style = "width:" + width + "em; height:" + lines + "em;"
                  })

...
+4
source share
3 answers

The code looks great. One possible improvement would be to externalize it as a reusable helper to avoid blurring your eyesight:

public static class TextAreaExtensions
{
    public static IHtmlString TextAreaAutoSizeFor<TModel, TProperty>(
        this HtmlHelper<TModel> htmlHelper,
        Expression<Func<TModel, TProperty>> expression,
        object htmlAttributes
    )
    {
        var model = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData).Model;
        var text = model as string ?? string.Empty;
        int width = 85;
        int lines = 1;
        string[] arr = text.Split(new string[] { "\r\n", "\n", "\r" }, StringSplitOptions.None);
        foreach (var str in arr)
        {
            if (str.Length / width > 0)
            {
                lines += str.Length / width + (str.Length % width <= width / 2 ? 1 : 0);
            }
            else
            {
                lines++;
            }
        }
        var attributes = new RouteValueDictionary(htmlAttributes);
        attributes["style"] = string.Format("width:{0}em; height:{1}em;", width, lines);
        return htmlHelper.TextAreaFor(expression, attributes);
    }
}

and in view:

@Html.TextAreaAutoSizeFor(m => m.Text, new { id = "text" })
+5
source

It looks great, you can also use the jQuery plugin to automatically compose text.

.

+3

LINQ:

var lines = Model.Text.Split( new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None )
  .Aggregate( 0, (total, next) => 
    total += next.Length <= width ? 1 
      : (int)Math.Ceiling( (double)next.Length / width ) );

Please note that there is a problem with the way you crack. If you login (if it is not) do have mixed \n, \rand \r\nthe end of the line, this division will be divided in order from left to right, so it will not ever break into the line \r\n, which will mean a blank line between \rand \n. So, you will see that I moved \r\nas the first row to split.

+2
source

All Articles