internal static void TextAreaHelper( HtmlHelper htmlHelper, XcstWriter output, ModelMetadata metadata, string name, IDictionary <string, object> rowsAndColumns, HtmlAttribs?htmlAttributes, string?innerHtmlPrefix = null) { string fullName = htmlHelper.ViewData.TemplateInfo.GetFullHtmlFieldName(name); if (String.IsNullOrEmpty(fullName)) { throw new ArgumentNullException(nameof(name)); } output.WriteStartElement("textarea"); HtmlAttributeHelper.WriteId(fullName, output); output.WriteAttributeString("name", fullName); HtmlAttributeHelper.WriteAttributes(rowsAndColumns, output); bool explicitRowsAndCols = rowsAndColumns != implicitRowsAndColumns; // If there are any errors for a named field, we add the css attribute. string?cssClass = (htmlHelper.ViewData.ModelState.TryGetValue(fullName, out ModelState modelState) && modelState.Errors.Count > 0) ? HtmlHelper.ValidationInputCssClassName : null; HtmlAttributeHelper.WriteClass(cssClass, htmlAttributes, output); HtmlAttributeHelper.WriteAttributes(htmlHelper.GetUnobtrusiveValidationAttributes(name, metadata), output); // name cannnot be overridden, and class was already written // explicit rows and cols cannot be overridden HtmlAttributeHelper.WriteAttributes( htmlAttributes, output, excludeFn: n => n == "name" || n == "class" || (explicitRowsAndCols && (n == "rows" || n == "cols"))); string?value; if (modelState?.Value != null) { value = modelState.Value.AttemptedValue; } else if (metadata.Model != null) { value = Convert.ToString(metadata.Model, CultureInfo.CurrentCulture); } else { value = String.Empty; } // The first newline is always trimmed when a TextArea is rendered, so we add an extra one // in case the value being rendered is something like "\r\nHello". output.WriteString((innerHtmlPrefix ?? Environment.NewLine) + value); output.WriteEndElement(); }
public static void UrlTemplate(HtmlHelper html, IXcstPackage package, ISequenceWriter <object> seqOutput) { XcstWriter output = DocumentWriter.CastElement(package, seqOutput); ViewDataDictionary viewData = html.ViewData; output.WriteStartElement("a"); output.WriteAttributeString("href", Convert.ToString(viewData.Model, CultureInfo.InvariantCulture)); output.WriteString(output.SimpleContent.Convert(viewData.TemplateInfo.FormattedModelValue)); output.WriteEndElement(); }
internal static void WriteOption(SelectListItem item, XcstWriter output) { output.WriteStartElement("option"); if (item.Value != null) { output.WriteAttributeString("value", item.Value); } HtmlAttributeHelper.WriteBoolean("selected", item.Selected, output); HtmlAttributeHelper.WriteBoolean("disabled", item.Disabled, output); output.WriteString(item.Text); output.WriteEndElement(); }
internal static void LabelHelper( HtmlHelper html, XcstWriter output, ModelMetadata metadata, string expression, string?labelText = null, HtmlAttribs?htmlAttributes = null) { string htmlFieldName = expression; string resolvedLabelText = labelText ?? metadata.DisplayName ?? metadata.PropertyName ?? htmlFieldName.Split('.').Last(); if (String.IsNullOrEmpty(resolvedLabelText)) { return; } string fullFieldName = html.ViewData.TemplateInfo.GetFullHtmlFieldName(htmlFieldName); output.WriteStartElement("label"); output.WriteAttributeString("for", TagBuilder.CreateSanitizedId(fullFieldName)); HtmlAttributeHelper.WriteAttributes(htmlAttributes, output); output.WriteString(resolvedLabelText); output.WriteEndElement(); }
internal static void ObjectTemplate(HtmlHelper html, IXcstPackage package, ISequenceWriter <object> seqOutput, TemplateHelpers.TemplateHelperDelegate templateHelper) { ViewDataDictionary viewData = html.ViewData; ModelMetadata modelMetadata = viewData.ModelMetadata; if (modelMetadata.Model is null || viewData.TemplateInfo.TemplateDepth > 1) { MetadataInstructions.DisplayTextHelper(html, seqOutput, modelMetadata); return; } var filteredProperties = DisplayInstructions.DisplayProperties(html); var groupedProperties = filteredProperties.GroupBy(p => p.GroupName()); bool createFieldset = groupedProperties.Any(g => g.Key != null); foreach (var group in groupedProperties) { XcstWriter?fieldsetWriter = null; if (createFieldset) { fieldsetWriter = DocumentWriter.CastElement(package, seqOutput); fieldsetWriter.WriteStartElement("fieldset"); fieldsetWriter.WriteStartElement("legend"); fieldsetWriter.WriteString(group.Key); fieldsetWriter.WriteEndElement(); } foreach (ModelMetadata propertyMeta in group) { XcstWriter?fieldWriter = null; if (!propertyMeta.HideSurroundingHtml) { XcstDelegate <object>?memberTemplate = DisplayInstructions.MemberTemplate(html, propertyMeta); if (memberTemplate != null) { memberTemplate(null !/* argument is not used */, fieldsetWriter ?? seqOutput); continue; } XcstWriter labelWriter = fieldsetWriter ?? DocumentWriter.CastElement(package, seqOutput); labelWriter.WriteStartElement("div"); labelWriter.WriteAttributeString("class", "display-label"); labelWriter.WriteString(propertyMeta.GetDisplayName() ?? String.Empty); labelWriter.WriteEndElement(); fieldWriter = fieldsetWriter ?? DocumentWriter.CastElement(package, seqOutput); fieldWriter.WriteStartElement("div"); fieldWriter.WriteAttributeString("class", "display-field"); } templateHelper( html, package, fieldWriter ?? fieldsetWriter ?? seqOutput, propertyMeta, htmlFieldName: propertyMeta.PropertyName, templateName: null, membersNames: null, DataBoundControlMode.ReadOnly, additionalViewData: null ); if (!propertyMeta.HideSurroundingHtml) { fieldWriter !.WriteEndElement(); // </div> } } if (createFieldset) { fieldsetWriter !.WriteEndElement(); // </fieldset> } } }
internal static void ValidationMessageHelper( HtmlHelper htmlHelper, XcstWriter output, ModelMetadata modelMetadata, string expression, string?validationMessage, HtmlAttribs?htmlAttributes, string?tag) { ViewDataDictionary viewData = htmlHelper.ViewData; string modelName = viewData.TemplateInfo.GetFullHtmlFieldName(expression); FormContext?formContext = htmlHelper.ViewContext.GetFormContextForClientValidation(); if (!viewData.ModelState.ContainsKey(modelName) && formContext is null) { return; } ModelState? modelState = viewData.ModelState[modelName]; ModelErrorCollection?modelErrors = modelState?.Errors; ModelError?modelError = (modelErrors is null || modelErrors.Count == 0) ? null : (modelErrors.FirstOrDefault(m => !String.IsNullOrEmpty(m.ErrorMessage)) ?? modelErrors[0]); if (modelError is null && formContext is null) { return; } if (String.IsNullOrEmpty(tag)) { tag = htmlHelper.ViewContext.ValidationMessageElement; } string validationClass = (modelError != null) ? HtmlHelper.ValidationMessageCssClassName : HtmlHelper.ValidationMessageValidCssClassName; output.WriteStartElement(tag !); HtmlAttributeHelper.WriteClass(validationClass, htmlAttributes, output); if (formContext != null) { bool replaceValidationMessageContents = String.IsNullOrEmpty(validationMessage); if (htmlHelper.ViewContext.UnobtrusiveJavaScriptEnabled) { output.WriteAttributeString("data-valmsg-for", modelName); output.WriteAttributeString("data-valmsg-replace", replaceValidationMessageContents.ToString().ToLowerInvariant()); } } // class was already written HtmlAttributeHelper.WriteAttributes(htmlAttributes, output, excludeFn: n => n == "class"); if (!String.IsNullOrEmpty(validationMessage)) { output.WriteString(validationMessage); } else if (modelError != null) { output.WriteString(GetUserErrorMessageOrDefault(modelError, modelState)); } output.WriteEndElement(); }
public static void ValidationSummary( HtmlHelper htmlHelper, XcstWriter output, bool includePropertyErrors = false, string?message = null, HtmlAttribs?htmlAttributes = null, string?headingTag = null) { if (htmlHelper is null) { throw new ArgumentNullException(nameof(htmlHelper)); } FormContext?formContext = htmlHelper.ViewContext.GetFormContextForClientValidation(); if (htmlHelper.ViewData.ModelState.IsValid) { if (formContext is null) { // No client side validation return; } // TODO: This isn't really about unobtrusive; can we fix up non-unobtrusive to get rid of this, too? if (htmlHelper.ViewContext.UnobtrusiveJavaScriptEnabled && !includePropertyErrors) { // No client-side updates return; } } string validationClass = (htmlHelper.ViewData.ModelState.IsValid) ? HtmlHelper.ValidationSummaryValidCssClassName : HtmlHelper.ValidationSummaryCssClassName; output.WriteStartElement("div"); HtmlAttributeHelper.WriteClass(validationClass, htmlAttributes, output); if (formContext != null) { if (htmlHelper.ViewContext.UnobtrusiveJavaScriptEnabled) { if (includePropertyErrors) { // Only put errors in the validation summary if they're supposed to be included there output.WriteAttributeString("data-valmsg-summary", "true"); } } } // class was already written HtmlAttributeHelper.WriteAttributes(htmlAttributes, output, excludeFn: n => n == "class"); if (!String.IsNullOrEmpty(message)) { if (String.IsNullOrEmpty(headingTag)) { headingTag = htmlHelper.ViewContext.ValidationSummaryMessageElement; } output.WriteStartElement(headingTag !); output.WriteString(message); output.WriteEndElement(); } output.WriteStartElement("ul"); bool empty = true; IEnumerable <ModelState> modelStates = GetModelStateList(htmlHelper, includePropertyErrors); foreach (ModelState modelState in modelStates) { foreach (ModelError modelError in modelState.Errors) { string?errorText = GetUserErrorMessageOrDefault(modelError, modelState: null); if (!String.IsNullOrEmpty(errorText)) { empty = false; output.WriteStartElement("li"); output.WriteString(errorText); output.WriteEndElement(); } } } if (empty) { output.WriteStartElement("li"); output.WriteAttributeString("style", "display:none"); output.WriteEndElement(); } output.WriteEndElement(); // </ul> output.WriteEndElement(); // </div> }