Пример #1
0
        /// <summary>
        /// Creates a new <see cref="ModelExplorer"/>.
        /// </summary>
        /// <param name="metadataProvider">The <see cref="IModelMetadataProvider"/>.</param>
        /// <param name="container">The container <see cref="ModelExplorer"/>.</param>
        /// <param name="metadata">The <see cref="ModelMetadata"/>.</param>
        /// <param name="modelAccessor">A model accessor function..</param>
        public ModelExplorer(
            IModelMetadataProvider metadataProvider,
            ModelExplorer container,
            ModelMetadata metadata,
            Func<object, object> modelAccessor)
        {
            if (metadataProvider == null)
            {
                throw new ArgumentNullException(nameof(metadataProvider));
            }

            if (container == null)
            {
                throw new ArgumentNullException(nameof(container));
            }

            if (metadata == null)
            {
                throw new ArgumentNullException(nameof(metadata));
            }

            _metadataProvider = metadataProvider;
            Container = container;
            Metadata = metadata;
            _modelAccessor = modelAccessor;
        }
        /// <summary>
        /// Invokes the view component.
        /// </summary>
        /// <param name="tableElementId">The ID of the table DOM element.</param>
        /// <param name="modelExplorer">The model explorer for the collection containing the table contents.</param>
        /// <param name="properties">The name of the properties of the model object to show in the table.</param>
        /// <param name="hiddenValues">Hidden values that should be included with the properties.</param>
        /// <param name="orderByProp">The property to order the rows by.</param>
        /// <param name="textAreas">Whether to render the properties in multi-line text areas.</param>
        /// <param name="startMinRows">The minimum number of rows in the table to start with.</param>
        /// <param name="defaultValues">The default values for each column, if any.</param>
        /// <param name="dropDownLists">The drop down lists to use, if any.</param>
        /// <param name="subPanelConfig">The configuration object for the subpanel (if any).</param>
        public IViewComponentResult Invoke(
            string tableElementId,
            ModelExplorer modelExplorer,
            string[] properties,
            IDictionary<string, string> hiddenValues,
            string orderByProp,
            int startMinRows,
            bool textAreas,
            IDictionary<string, object> defaultValues,
            IList<DropDownList> dropDownLists,
            SubPanelConfig subPanelConfig)
        {
            var props = properties.Where(prop => prop != null).ToArray();
            var collection = GetOrderedCollection(modelExplorer, orderByProp);
            var elementMetadata = modelExplorer.Metadata.ElementMetadata;
            string collectionName = modelExplorer.Metadata.PropertyName;

            JArray columns = GetColumnInfo
            (
                props,
                hiddenValues,
                textAreas,
                defaultValues,
                dropDownLists,
                elementMetadata
            );

            var initDataProperties = subPanelConfig == null
                ? props
                : props.Union(new[] { subPanelConfig.ContentsPropertyName });

            JArray initData = GetInitialData
            (
                hiddenValues,
                collection,
                dropDownLists,
                elementMetadata,
                initDataProperties
            );

            return View
            (
                new DynamicTableConfig
                (
                    tableElementId,
                    collectionName,
                    columns,
                    initData,
                    startMinRows,
                    textAreas,
                    dropDownLists,
                    subPanelConfig
                )
            );
        }
Пример #3
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ModelExpression"/> class.
        /// </summary>
        /// <param name="name">
        /// String representation of the <see cref="System.Linq.Expressions.Expression"/> of interest.
        /// </param>
        /// <param name="modelExplorer">
        /// Includes the model and metadata about the <see cref="System.Linq.Expressions.Expression"/> of interest.
        /// </param>
        public ModelExpression(string name, ModelExplorer modelExplorer)
        {
            if (name == null)
            {
                throw new ArgumentNullException(nameof(name));
            }

            if (modelExplorer == null)
            {
                throw new ArgumentNullException(nameof(modelExplorer));
            }

            Name = name;
            ModelExplorer = modelExplorer;
        }
        public JsTreeTagHelperTests()
        {
            JsTree tree = new JsTree();
            tree.SelectedIds.Add(4567);
            tree.SelectedIds.Add(12345);
            tree.Nodes.Add(new JsTreeNode("Test"));
            tree.Nodes[0].Nodes.Add(new JsTreeNode(12345, "Test1"));
            tree.Nodes[0].Nodes.Add(new JsTreeNode(23456, "Test2"));

            EmptyModelMetadataProvider provider = new EmptyModelMetadataProvider();
            ModelExplorer explorer = new ModelExplorer(provider, provider.GetMetadataForProperty(typeof(JsTreeView), "JsTree"), tree);

            helper = new JsTreeTagHelper();
            helper.For = new ModelExpression("JsTree", explorer);
            output = new TagHelperOutput("div", new TagHelperAttributeList(), (useCachedResult, encoder) => null);
        }
        /// <summary>
        /// Returns a collection, ordered by the property with the given name.
        /// </summary>
        private IEnumerable<object> GetOrderedCollection(ModelExplorer modelExplorer, string orderByProp)
        {
            var orderProp = modelExplorer.Metadata.ElementMetadata.Properties[orderByProp];
            var collection = (modelExplorer.Model as IEnumerable)?.Cast<object>();

            if (collection == null)
                return null;

            if (orderProp.ModelType == typeof(string))
                return collection.OrderBy(obj => (string) orderProp.PropertyGetter(obj));
            else if (orderProp.ModelType == typeof(int))
                return collection.OrderBy(obj => (int) orderProp.PropertyGetter(obj));
            else
                throw new InvalidOperationException("Unsupported order property type.");
        }
Пример #6
0
        private string GetInputType(ModelExplorer modelExplorer, out string inputTypeHint)
        {
            foreach (var hint in GetInputTypeHints(modelExplorer))
            {
                string inputType;
                if (_defaultInputTypes.TryGetValue(hint, out inputType))
                {
                    inputTypeHint = hint;
                    return inputType;
                }
            }

            inputTypeHint = InputType.Text.ToString().ToLowerInvariant();
            return inputTypeHint;
        }
Пример #7
0
        // Get a fall-back format based on the metadata.
        private string GetFormat(ModelExplorer modelExplorer, string inputTypeHint, string inputType)
        {
            string format;
            string rfc3339Format;
            if (string.Equals("decimal", inputTypeHint, StringComparison.OrdinalIgnoreCase) &&
                string.Equals("text", inputType, StringComparison.Ordinal) &&
                string.IsNullOrEmpty(modelExplorer.Metadata.EditFormatString))
            {
                // Decimal data is edited using an <input type="text"/> element, with a reasonable format.
                // EditFormatString has precedence over this fall-back format.
                format = "{0:0.00}";
            }
            else if (_rfc3339Formats.TryGetValue(inputType, out rfc3339Format) &&
                ViewContext.Html5DateRenderingMode == Html5DateRenderingMode.Rfc3339 &&
                !modelExplorer.Metadata.HasNonDefaultEditFormat &&
                (typeof(DateTime) == modelExplorer.Metadata.UnderlyingOrModelType || typeof(DateTimeOffset) == modelExplorer.Metadata.UnderlyingOrModelType))
            {
                // Rfc3339 mode _may_ override EditFormatString in a limited number of cases e.g. EditFormatString
                // must be a default format (i.e. came from a built-in [DataType] attribute).
                format = rfc3339Format;
            }
            else
            {
                // Otherwise use EditFormatString, if any.
                format = modelExplorer.Metadata.EditFormatString;
            }

            return format;
        }
Пример #8
0
        private TagBuilder GenerateTextBox(ModelExplorer modelExplorer, string inputTypeHint, string inputType)
        {
            var format = Format;
            if (string.IsNullOrEmpty(format))
            {
                format = GetFormat(modelExplorer, inputTypeHint, inputType);
            }

            var htmlAttributes = new Dictionary<string, object>
            {
                { "type", inputType }
            };

            if (string.Equals(inputType, "file") && string.Equals(inputTypeHint, TemplateRenderer.IEnumerableOfIFormFileName))
            {
                htmlAttributes["multiple"] = "multiple";
            }

            return Generator.GenerateTextBox(
                ViewContext,
                modelExplorer,
                For.Name,
                value: modelExplorer.Model,
                format: format,
                htmlAttributes: htmlAttributes);
        }
Пример #9
0
        private TagBuilder GenerateRadio(ModelExplorer modelExplorer)
        {
            // Note empty string is allowed.
            if (Value == null)
            {
                throw new InvalidOperationException(Resources.FormatInputTagHelper_ValueRequired(
                    "<input>",
                    nameof(Value).ToLowerInvariant(),
                    "type",
                    "radio"));
            }

            return Generator.GenerateRadioButton(
                ViewContext,
                modelExplorer,
                For.Name,
                Value,
                isChecked: null,
                htmlAttributes: null);
        }
Пример #10
0
        private void GenerateCheckBox(ModelExplorer modelExplorer, TagHelperOutput output)
        {
            if (typeof(bool) != modelExplorer.ModelType)
            {
                throw new InvalidOperationException(Resources.FormatInputTagHelper_InvalidExpressionResult(
                    "<input>",
                    ForAttributeName,
                    modelExplorer.ModelType.FullName,
                    typeof(bool).FullName,
                    "type",
                    "checkbox"));
            }

            // Prepare to move attributes from current element to <input type="checkbox"/> generated just below.
            var htmlAttributes = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);

            // Perf: Avoid allocating enumerator
            // Construct attributes correctly (first attribute wins).
            for (var i = 0; i < output.Attributes.Count; i++)
            {
                var attribute = output.Attributes[i];
                if (!htmlAttributes.ContainsKey(attribute.Name))
                {
                    htmlAttributes.Add(attribute.Name, attribute.Value);
                }
            }

            var checkBoxTag = Generator.GenerateCheckBox(
                ViewContext,
                modelExplorer,
                For.Name,
                isChecked: null,
                htmlAttributes: htmlAttributes);
            if (checkBoxTag != null)
            {
                // Do not generate current element's attributes or tags. Instead put both <input type="checkbox"/> and
                // <input type="hidden"/> into the output's Content.
                output.Attributes.Clear();
                output.TagName = null;

                var renderingMode =
                    output.TagMode == TagMode.SelfClosing ? TagRenderMode.SelfClosing : TagRenderMode.StartTag;
                checkBoxTag.TagRenderMode = renderingMode;
                output.Content.AppendHtml(checkBoxTag);

                var hiddenForCheckboxTag = Generator.GenerateHiddenForCheckbox(ViewContext, modelExplorer, For.Name);
                if (hiddenForCheckboxTag != null)
                {
                    hiddenForCheckboxTag.TagRenderMode = renderingMode;

                    if (ViewContext.FormContext.CanRenderAtEndOfForm)
                    {
                        ViewContext.FormContext.EndOfFormContent.Add(hiddenForCheckboxTag);
                    }
                    else
                    {
                        output.Content.AppendHtml(hiddenForCheckboxTag);
                    }
                }
            }
        }
Пример #11
0
        // A variant of TemplateRenderer.GetViewNames(). Main change relates to bool? handling.
        private static IEnumerable<string> GetInputTypeHints(ModelExplorer modelExplorer)
        {
            if (!string.IsNullOrEmpty(modelExplorer.Metadata.TemplateHint))
            {
                yield return modelExplorer.Metadata.TemplateHint;
            }

            if (!string.IsNullOrEmpty(modelExplorer.Metadata.DataTypeName))
            {
                yield return modelExplorer.Metadata.DataTypeName;
            }

            // In most cases, we don't want to search for Nullable<T>. We want to search for T, which should handle
            // both T and Nullable<T>. However we special-case bool? to avoid turning an <input/> into a <select/>.
            var fieldType = modelExplorer.ModelType;
            if (typeof(bool?) != fieldType)
            {
                fieldType = modelExplorer.Metadata.UnderlyingOrModelType;
            }

            foreach (string typeName in TemplateRenderer.GetTypeNames(modelExplorer.Metadata, fieldType))
            {
                yield return typeName;
            }
        }
Пример #12
0
 public bool Visited(ModelExplorer modelExplorer)
 {
     return _visitedObjects.Contains(modelExplorer.Model ?? modelExplorer.Metadata.ModelType);
 }
Пример #13
0
        /// <summary>
        /// Creates a new <see cref="ModelExplorer"/>.
        /// </summary>
        /// <param name="metadataProvider">The <see cref="IModelMetadataProvider"/>.</param>
        /// <param name="container">The container <see cref="ModelExplorer"/>.</param>
        /// <param name="metadata">The <see cref="ModelMetadata"/>.</param>
        /// <param name="model">The model object. May be <c>null</c>.</param>
        public ModelExplorer(
            IModelMetadataProvider metadataProvider,
            ModelExplorer container,
            ModelMetadata metadata,
            object model)
        {
            if (metadataProvider == null)
            {
                throw new ArgumentNullException(nameof(metadataProvider));
            }

            if (metadata == null)
            {
                throw new ArgumentNullException(nameof(metadata));
            }

            _metadataProvider = metadataProvider;
            Container = container;
            Metadata = metadata;
            _model = model;
        }