Example #1
0
        private FlowFormField FieldFor <TProperty>(Expression <Func <TModel, TProperty> > expression, bool containsSection, FieldConfiguration fieldConfiguration = null)
        {
            /*
             * Renders a field for a non-boolean property of the model
             */

            fieldConfiguration = fieldConfiguration ?? new FieldConfiguration();

            if (fieldConfiguration.HideIfNull && fieldConfiguration.ReadOnly && GetValue(expression) == null)
            {
                return(null);
            }

            var htmlAttrs  = Helper.ObjectToDictionary(fieldConfiguration.HtmlAttributes);
            var type       = ElementType.Text;
            var grid       = default(Grid);
            var selectList = default(MultiSelectList);
            var metadata   = ModelMetadata.FromLambdaExpression(expression, _htmlHelper.ViewData);

            // Label
            var labelHtml = LabelHtml(expression, fieldConfiguration);

            if (fieldConfiguration.ReadOnly)
            {
                labelHtml = labelHtml.ReReplace(@"</?label.*?>", "", RegexOptions.IgnoreCase);
            }

            if (fieldConfiguration.ReadOnly && expression.ReturnType.Name != "Grid`1")
            {
                var value      = (GetValue(expression) ?? "?");
                var fi         = value.GetType().GetField(value.ToString());
                var attributes = fi != null ? (DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute), false) : new DescriptionAttribute[] { };

                var stringValue = (attributes.Length > 0) ? attributes[0].Description : value.ToString();

                return(new FlowFormField(_writer, containsSection, labelHtml, (new HtmlString(stringValue)).ToString(), parentClass: fieldConfiguration.ParentClass));
            }

            var validators = metadata.GetValidators(_htmlHelper.ViewContext.Controller.ControllerContext);

            var classes = new ClassBuilder();

            if (htmlAttrs.ContainsKey("class"))
            {
                classes.Add((string)htmlAttrs["class"]);
            }

            if (metadata.IsRequired && (!metadata.ModelType.IsEnum || fieldConfiguration.Exclude == null || fieldConfiguration.Exclude.Length == 0))
            {
                classes.Add("required");
            }
            else
            {
                labelHtml = labelHtml.Replace("</label>", " <em>(Optional)</em></label>");
            }

            switch (metadata.DataTypeName)
            {
            case "Digits":
            case "CreditCard":
                classes.Add(metadata.DataTypeName.Replace("-", "").ToLower());
                break;

            case "IPAddress":
                classes.Add("ip-address");
                break;

            case "MultilineText":
                type = ElementType.TextArea;
                break;
            }
            switch (metadata.ModelType.Name)
            {
            case "Double":
                classes.Add("number");
                break;

            case "Int32":
                classes.Add("integer");
                break;

            case "Email":
                classes.Add("email");
                break;

            case "Password":
                type = ElementType.Password;
                break;

            case "Date":
                classes.Add("date");
                break;

            case "HttpPostedFileBase":
                htmlAttrs["type"] = "file";
                break;
            }

            if (metadata.ModelType.IsEnum && metadata.ModelType.IsDefined(typeof(FlagsAttribute), false))
            {
                type = ElementType.Select;
                var list           = (IEnumerable <object>)EnumInfo.CreateList(metadata.ModelType, fieldConfiguration.Exclude);
                var selectedValues = GetSelectedEnums((Enum)metadata.Model, fieldConfiguration.Exclude).ToList();
                selectList = new MultiSelectList(list, "Value", "Display", selectedValues);
            }
            else if (metadata.ModelType.IsEnum || (
                         metadata.ModelType.IsGenericType &&
                         metadata.ModelType.GetGenericTypeDefinition().FullName == "System.Nullable`1" &&
                         metadata.ModelType.GetGenericArguments()[0].IsEnum
                         ) || (
                         typeof(IEnumerable).IsAssignableFrom(metadata.ModelType) &&
                         !typeof(string).IsAssignableFrom(metadata.ModelType) &&
                         metadata.ModelType.GetGenericArguments()[0].IsEnum
                         )
                     )
            {
                type = ElementType.Select;
                var list           = (IEnumerable <object>)EnumInfo.CreateList(metadata.ModelType.IsGenericType ? metadata.ModelType.GetGenericArguments()[0] : metadata.ModelType, fieldConfiguration.Exclude);
                var selectedValues = GetSelected(metadata.Model);
                selectList = new MultiSelectList(list, "Value", "Display", selectedValues);
            }

            foreach (var rule in validators.SelectMany(v => v.GetClientValidationRules()))
            {
                switch (rule.ValidationType)
                {
                case "range":
                    classes.Add(string.Format("range([{0},{1}])", rule.ValidationParameters["min"], rule.ValidationParameters["max"]));
                    break;

                case "min":
                    classes.Add(string.Format("min({0})", rule.ValidationParameters["min"]));
                    break;

                case "max":
                    classes.Add(string.Format("max({0})", rule.ValidationParameters["max"]));
                    break;

                case "regex":
                    classes.Add(string.Format("match(/{0}/)", rule.ValidationParameters["pattern"]));
                    break;

                case "length":
                case "maxlength":
                    if (type == ElementType.Text || type == ElementType.Password)
                    {
                        htmlAttrs["maxlength"] = rule.ValidationParameters["max"];
                    }
                    else
                    {
                        classes.Add(string.Format("maxlength({0})", rule.ValidationParameters["max"]));
                    }
                    break;

                case "minlength":
                    classes.Add(string.Format("minlength({0})", rule.ValidationParameters["min"]));
                    break;

                case "rangelength":
                    classes.Add(string.Format("rangelength([{0},{1}])", rule.ValidationParameters["min"], rule.ValidationParameters["max"]));
                    break;

                case "equalto":
                    classes.Add(string.Format("equalTo('#{0}')", rule.ValidationParameters["other"].ToString().Split('.')[1]));
                    labelHtml = labelHtml.Replace(" <em>(Optional)</em>", "");
                    break;

                case "existsin":
                    type       = ElementType.Select;
                    selectList = GetSelectListFromCollection(expression, metadata, rule);
                    break;

                case "grid":
                    grid = GetGrid(expression, metadata, rule);
                    break;

                case "notrequired":
                    labelHtml = labelHtml.Replace(" <em>(Optional)</em>", "");
                    break;

                case "filetype":
                    classes.Add(string.Format("accept('{0}')", rule.ValidationParameters["extension"]));
                    fieldConfiguration.Tip = fieldConfiguration.Tip ?? string.Format("Filetype must be: {0}", rule.ValidationParameters["pretty-extension"]);
                    break;
                }
            }

            if (classes.ToString().Trim() != "")
            {
                htmlAttrs["class"] = classes.ToString();
            }

            if (fieldConfiguration.As.HasValue)
            {
                var validOverride        = false;
                var overrideErrorMessage = "";
                switch (type)
                {
                case ElementType.Select:
                    switch (fieldConfiguration.As.Value)
                    {
                    case ElementType.Checkboxes:
                    case ElementType.RadioButtons:
                    case ElementType.Text:
                        type          = fieldConfiguration.As.Value;
                        validOverride = true;
                        break;
                    }
                    break;

                case ElementType.Text:
                    switch (fieldConfiguration.As.Value)
                    {
                    case ElementType.Checkboxes:
                    case ElementType.RadioButtons:
                    case ElementType.Select:
                        if (fieldConfiguration.PossibleValues != null)
                        {
                            selectList    = fieldConfiguration.PossibleValues;
                            type          = fieldConfiguration.As.Value;
                            validOverride = true;
                        }
                        else
                        {
                            overrideErrorMessage = "I was expecting a list.";
                        }
                        break;
                    }
                    break;
                }
                if (!validOverride)
                {
                    throw new ApplicationException(string.Format("FieldConfiguration{{ As = {0} }} not valid for field: {1} (which defaults to {2}). {3}",
                                                                 fieldConfiguration.As.Value, expression, type, overrideErrorMessage));
                }
            }

            var elementHtml = string.Empty;
            var errorHtml   = string.Empty;
            var isValid     = true;

            if (grid != null)
            {
                elementHtml = RenderGrid(grid, fieldConfiguration.ReadOnly);
                isValid     = GetErrors(expression, out errorHtml);
            }
            else
            {
                switch (type)
                {
                case ElementType.Text:
                    elementHtml = _htmlHelper.TextBoxFor(expression, htmlAttrs).ToHtmlString();
                    break;

                case ElementType.Password:
                    elementHtml = _htmlHelper.PasswordFor(expression, htmlAttrs).ToHtmlString();
                    break;

                case ElementType.TextArea:
                    elementHtml = _htmlHelper.TextAreaFor(expression, htmlAttrs).ToHtmlString();
                    break;

                case ElementType.Select:
                    if (typeof(IEnumerable).IsAssignableFrom(metadata.ModelType) &&
                        !typeof(string).IsAssignableFrom(metadata.ModelType))
                    {
                        elementHtml = _htmlHelper.ListBoxFor(expression, selectList, htmlAttrs).ToHtmlString();
                    }
                    else
                    {
                        elementHtml = _htmlHelper.DropDownListFor(expression, selectList, fieldConfiguration.Label, htmlAttrs).ToHtmlString();
                    }
                    break;

                case ElementType.Checkboxes:
                case ElementType.RadioButtons:
                    // TODO: Use HTML Attributes
                    var typeString = type == ElementType.Checkboxes ? "checkbox" : "radio";
                    elementHtml += HelperDefinitions.BeginInputList(typeString);
                    elementHtml += string.Join("", selectList.Select(i => HelperDefinitions.InputListItem(typeString, expression.GetFieldName(), i.Value, i.Text, i.Selected).ToString()));
                    elementHtml += HelperDefinitions.EndInputList();
                    break;
                }
                isValid = GetErrors(expression, out errorHtml);
            }

            elementHtml = (fieldConfiguration.Before ?? "") + elementHtml + (fieldConfiguration.After ?? "");

            return(new FlowFormField(_writer, containsSection, labelHtml, elementHtml, errorHtml, isValid, fieldConfiguration.Hint, fieldConfiguration.Tip, fieldConfiguration.HideTip, fieldConfiguration.HintClass, fieldConfiguration.ParentClass, fieldConfiguration.DisplayFieldName));
        }