mirror of https://github.com/abpframework/abp.git
6 changed files with 861 additions and 0 deletions
@ -0,0 +1,147 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using JetBrains.Annotations; |
|||
using Microsoft.AspNetCore.Razor.TagHelpers; |
|||
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.DatePicker; |
|||
|
|||
public abstract class |
|||
AbpDatePickerBaseTagHelper<TTagHelper> : AbpTagHelper<TTagHelper, AbpDatePickerBaseTagHelperService<TTagHelper>> |
|||
where TTagHelper : AbpDatePickerBaseTagHelper<TTagHelper> |
|||
|
|||
{ |
|||
public string Label { get; set; } |
|||
|
|||
public string LabelTooltip { get; set; } |
|||
|
|||
public string LabelTooltipIcon { get; set; } = "bi-info-circle"; |
|||
|
|||
public string LabelTooltipPlacement { get; set; } = "right"; |
|||
|
|||
public bool LabelTooltipHtml { get; set; } = false; |
|||
|
|||
[HtmlAttributeName("info")] |
|||
public string InfoText { get; set; } |
|||
|
|||
[HtmlAttributeName("disabled")] |
|||
public bool IsDisabled { get; set; } = false; |
|||
|
|||
[HtmlAttributeName("readonly")] |
|||
public bool? IsReadonly { get; set; } = false; |
|||
|
|||
public bool AutoFocus { get; set; } |
|||
|
|||
[HtmlAttributeName("type")] |
|||
public string InputTypeName { get; set; } = "text"; |
|||
|
|||
public AbpFormControlSize Size { get; set; } = AbpFormControlSize.Default; |
|||
|
|||
[HtmlAttributeName("required-symbol")] |
|||
public bool DisplayRequiredSymbol { get; set; } = true; |
|||
|
|||
[HtmlAttributeName("asp-format")] |
|||
public string Format { get; set; } |
|||
|
|||
public string Name { get; set; } |
|||
|
|||
public string Value { get; set; } |
|||
|
|||
public bool SuppressLabel { get; set; } |
|||
|
|||
|
|||
// Min and Max date
|
|||
public DateTime? MinDate { get; set; } |
|||
|
|||
public DateTime? MaxDate { get; set; } |
|||
|
|||
// Max span between start and end date
|
|||
public object? MaxSpan { get; set; } |
|||
|
|||
// Show dropdowns
|
|||
public bool ShowDropdowns { get; set; } = true; |
|||
|
|||
// Min and Max year
|
|||
public int? MinYear { get; set; } |
|||
|
|||
public int? MaxYear { get; set; } |
|||
|
|||
// Show week numbers
|
|||
public AbpDatePickerWeekNumbers WeekNumbers { get; set; } = AbpDatePickerWeekNumbers.None; |
|||
|
|||
// Time picker
|
|||
public bool? TimePicker { get; set; } |
|||
|
|||
// Time picker increment
|
|||
public int? TimePickerIncrement { get; set; } |
|||
|
|||
// Time picker 24 hour
|
|||
public bool? TimePicker24Hour { get; set; } |
|||
|
|||
// Time picker seconds
|
|||
public bool? TimePickerSeconds { get; set; } |
|||
|
|||
// Ranges object
|
|||
public List<AbpDatePickerRange> Ranges { get; set; } |
|||
|
|||
// Show custom range label
|
|||
public bool ShowCustomRangeLabel { get; set; } = true; |
|||
|
|||
// Always show calendar
|
|||
public bool AlwaysShowCalendars { get; set; } = false; |
|||
|
|||
// Opens date picker on left or right or center of the input
|
|||
public AbpDatePickerOpens Opens { get; set; } = AbpDatePickerOpens.Center; |
|||
|
|||
// Drops down or up or auto
|
|||
public AbpDatePickerDrops Drops { get; set; } = AbpDatePickerDrops.Down; |
|||
|
|||
// Button classes
|
|||
[CanBeNull] |
|||
public string ButtonClasses { get; set; } |
|||
|
|||
// Apply class to all buttons
|
|||
[CanBeNull] |
|||
public string ApplyButtonClasses { get; set; } |
|||
|
|||
// Cancel class to all buttons
|
|||
[CanBeNull] |
|||
public string CancelButtonClasses { get; set; } |
|||
|
|||
// Locale
|
|||
[CanBeNull] |
|||
public object Locale { get; set; } |
|||
|
|||
// Auto apply
|
|||
public bool AutoApply { get; set; } = true; |
|||
|
|||
// Linked calendars
|
|||
public bool? LinkedCalendars { get; set; } |
|||
|
|||
// Auto update input
|
|||
public bool AutoUpdateInput { get; set; } = false; |
|||
|
|||
// Parent element
|
|||
[CanBeNull] |
|||
public string ParentEl { get; set; } |
|||
|
|||
// public DatePickerType Type { get; set; } = DatePickerType.Date;
|
|||
|
|||
[CanBeNull] |
|||
public string DateFormat { get; set; } |
|||
|
|||
public bool OpenButton { get; set; } = true; |
|||
|
|||
public bool ClearButton { get; set; } = true; |
|||
|
|||
public bool IsUtc { get; set; } = false; |
|||
|
|||
public bool IsIso { get; set; } = false; |
|||
|
|||
[CanBeNull] |
|||
public object Options { get; set; } |
|||
|
|||
protected AbpDatePickerBaseTagHelper(AbpDatePickerBaseTagHelperService<TTagHelper> service) : base(service) |
|||
{ |
|||
} |
|||
} |
|||
@ -0,0 +1,643 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.ComponentModel.DataAnnotations; |
|||
using System.Linq; |
|||
using System.Text.Encodings.Web; |
|||
using System.Threading.Tasks; |
|||
using JetBrains.Annotations; |
|||
using Localization.Resources.AbpUi; |
|||
using Microsoft.AspNetCore.Mvc.Rendering; |
|||
using Microsoft.AspNetCore.Mvc.TagHelpers; |
|||
using Microsoft.AspNetCore.Mvc.ViewFeatures; |
|||
using Microsoft.AspNetCore.Razor.TagHelpers; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Localization; |
|||
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers; |
|||
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button; |
|||
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions; |
|||
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form; |
|||
using Volo.Abp.Json; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.DatePicker; |
|||
|
|||
public abstract class AbpDatePickerBaseTagHelperService<TTagHelper> : AbpTagHelperService<TTagHelper> |
|||
where TTagHelper : AbpDatePickerBaseTagHelper<TTagHelper> |
|||
{ |
|||
protected readonly Dictionary<Type,Func<object,string>> SupportedInputTypes = new() { |
|||
{typeof(string), o => DateTime.Parse((string)o).ToString("O")}, |
|||
{typeof(DateTime), o => ((DateTime) o).ToString("O")}, |
|||
{typeof(DateTime?), o => ((DateTime?) o)?.ToString("O")}, |
|||
{typeof(DateTimeOffset), o => ((DateTimeOffset) o).ToString("O")}, |
|||
{typeof(DateTimeOffset?), o => ((DateTimeOffset?) o)?.ToString("O")} |
|||
}; |
|||
|
|||
protected readonly IJsonSerializer JsonSerializer; |
|||
protected readonly IHtmlGenerator Generator; |
|||
protected readonly HtmlEncoder Encoder; |
|||
protected readonly IServiceProvider ServiceProvider; |
|||
protected readonly IAbpTagHelperLocalizer TagHelperLocalizer; |
|||
protected virtual string TagName { get; set; } = "abp-date-picker"; |
|||
protected IStringLocalizer<AbpUiResource> L { get; } |
|||
protected InputTagHelper InputTagHelper { get; set; } |
|||
protected abstract TagHelperOutput TagHelperOutput { get; set; } |
|||
|
|||
protected AbpDatePickerBaseTagHelperService(IJsonSerializer jsonSerializer, IHtmlGenerator generator, |
|||
HtmlEncoder encoder, IServiceProvider serviceProvider, IStringLocalizer<AbpUiResource> l, |
|||
IAbpTagHelperLocalizer tagHelperLocalizer) |
|||
{ |
|||
JsonSerializer = jsonSerializer; |
|||
Generator = generator; |
|||
Encoder = encoder; |
|||
ServiceProvider = serviceProvider; |
|||
L = l; |
|||
TagHelperLocalizer = tagHelperLocalizer; |
|||
|
|||
InputTagHelper = new InputTagHelper(Generator) { InputTypeName = "text" }; |
|||
} |
|||
|
|||
protected virtual T GetAttribute<T>() where T : Attribute |
|||
{ |
|||
return GetAttributeAndModelExpression<T>(out _); |
|||
} |
|||
|
|||
protected abstract T GetAttributeAndModelExpression<T>(out ModelExpression modelExpression) where T : Attribute; |
|||
|
|||
|
|||
public async override Task ProcessAsync(TagHelperContext context, TagHelperOutput output) |
|||
{ |
|||
TagHelperOutput = new TagHelperOutput("input", GetInputAttributes(context, output), (_, _) => Task.FromResult<TagHelperContent>(new DefaultTagHelperContent())); |
|||
|
|||
InputTagHelper.ViewContext = TagHelper.ViewContext; |
|||
|
|||
if (!TagHelper.Name.IsNullOrEmpty()) |
|||
{ |
|||
InputTagHelper.Name = TagHelper.Name; |
|||
} |
|||
|
|||
if (!TagHelper.Value.IsNullOrEmpty()) |
|||
{ |
|||
InputTagHelper.Value = TagHelper.Value; |
|||
} |
|||
|
|||
AddDisabledAttribute(TagHelperOutput); |
|||
AddAutoFocusAttribute(TagHelperOutput); |
|||
AddFormControls(context, output, TagHelperOutput); |
|||
AddPlaceholderAttribute(TagHelperOutput); |
|||
AddInfoTextId(TagHelperOutput); |
|||
|
|||
// Open and close button
|
|||
var openButtonContent = TagHelper.OpenButton |
|||
? await ProcessButtonAndGetContentAsync(context, output, "calendar", "open") |
|||
: ""; |
|||
var clearButtonContent = TagHelper.ClearButton |
|||
? await ProcessButtonAndGetContentAsync(context, output, "times", "clear") |
|||
: ""; |
|||
|
|||
var labelContent = TagHelper.SuppressLabel ? "" : await GetLabelAsHtmlAsync(context, output, TagHelperOutput); |
|||
var infoContent = GetInfoAsHtml(context, output, TagHelperOutput); |
|||
var validationContent = await GetValidationAsHtmlAsync(context, output); |
|||
|
|||
var inputGroup = new TagHelperOutput("div", |
|||
new TagHelperAttributeList(new[] { new TagHelperAttribute("class", "input-group") }), |
|||
(_, _) => Task.FromResult<TagHelperContent>(new DefaultTagHelperContent())); |
|||
inputGroup.Content.AppendHtml( |
|||
TagHelperOutput.Render(Encoder) + openButtonContent + clearButtonContent + infoContent |
|||
); |
|||
|
|||
var abpDatePickerTag = new TagHelperOutput(TagName, GetBaseTagAttributes(context, output), |
|||
(_, _) => Task.FromResult<TagHelperContent>(new DefaultTagHelperContent())); |
|||
abpDatePickerTag.Content.AppendHtml(inputGroup.Render(Encoder)); |
|||
abpDatePickerTag.Content.AppendHtml(validationContent); |
|||
abpDatePickerTag.Content.AppendHtml(GetExtraInputHtml(context, output)); |
|||
|
|||
var innerHtml = labelContent + abpDatePickerTag.Render(Encoder); |
|||
|
|||
var order = GetOrder(); |
|||
|
|||
AddGroupToFormGroupContents( |
|||
context, |
|||
GetPropertyName(), |
|||
SurroundInnerHtmlAndGet(context, output, innerHtml), |
|||
order |
|||
); |
|||
|
|||
|
|||
output.TagMode = TagMode.StartTagAndEndTag; |
|||
output.TagName = "div"; |
|||
LeaveOnlyGroupAttributes(context, output); |
|||
output.Attributes.AddClass("mb-3"); |
|||
|
|||
output.Content.AppendHtml(innerHtml); |
|||
} |
|||
|
|||
protected virtual TagHelperAttributeList GetInputAttributes(TagHelperContext context, TagHelperOutput output) |
|||
{ |
|||
var groupPrefix = "group-"; |
|||
|
|||
var tagHelperAttributes = output.Attributes.Where(a => !a.Name.StartsWith(groupPrefix)).ToList(); |
|||
|
|||
var attrList = new TagHelperAttributeList(); |
|||
|
|||
foreach (var tagHelperAttribute in tagHelperAttributes) |
|||
{ |
|||
attrList.Add(tagHelperAttribute); |
|||
} |
|||
|
|||
attrList.Add("type", "text"); |
|||
|
|||
if (attrList.ContainsName("value")) |
|||
{ |
|||
attrList.Remove(attrList.First(a => a.Name == "value")); |
|||
} |
|||
|
|||
if (!TagHelper.Name.IsNullOrEmpty() && !attrList.ContainsName("name")) |
|||
{ |
|||
attrList.Add("name", TagHelper.Name); |
|||
} |
|||
|
|||
if (!attrList.ContainsName("autocomplete")) |
|||
{ |
|||
attrList.Add("autocomplete", "off"); |
|||
} |
|||
|
|||
return attrList; |
|||
} |
|||
protected virtual void LeaveOnlyGroupAttributes(TagHelperContext context, TagHelperOutput output) |
|||
{ |
|||
var groupPrefix = "group-"; |
|||
var tagHelperAttributes = output.Attributes.Where(a => a.Name.StartsWith(groupPrefix)).ToList(); |
|||
|
|||
output.Attributes.Clear(); |
|||
|
|||
foreach (var tagHelperAttribute in tagHelperAttributes) |
|||
{ |
|||
var nameWithoutPrefix = tagHelperAttribute.Name.Substring(groupPrefix.Length); |
|||
var newAttribute = new TagHelperAttribute(nameWithoutPrefix, tagHelperAttribute.Value); |
|||
output.Attributes.Add(newAttribute); |
|||
} |
|||
} |
|||
|
|||
protected virtual string SurroundInnerHtmlAndGet(TagHelperContext context, TagHelperOutput output, string innerHtml) |
|||
{ |
|||
return "<div class=\"mb-3\">" + |
|||
Environment.NewLine + innerHtml + Environment.NewLine + |
|||
"</div>"; |
|||
} |
|||
|
|||
protected abstract string GetPropertyName(); |
|||
|
|||
protected virtual void AddGroupToFormGroupContents(TagHelperContext context, string propertyName, string html, |
|||
int order) |
|||
{ |
|||
var list = context.GetValue<List<FormGroupItem>>(FormGroupContents) ?? new List<FormGroupItem>(); |
|||
|
|||
if (!list.Any(igc => igc.HtmlContent.Contains("id=\"" + propertyName.Replace('.', '_') + "\""))) |
|||
{ |
|||
list.Add(new FormGroupItem { HtmlContent = html, Order = order, PropertyName = propertyName }); |
|||
} |
|||
} |
|||
|
|||
protected abstract int GetOrder(); |
|||
protected abstract void AddBaseTagAttributes(TagHelperAttributeList attributes); |
|||
|
|||
protected virtual string GetExtraInputHtml(TagHelperContext context, TagHelperOutput output) |
|||
{ |
|||
return string.Empty; |
|||
} |
|||
|
|||
protected TagHelperAttributeList GetBaseTagAttributes(TagHelperContext context, TagHelperOutput output) |
|||
{ |
|||
var groupPrefix = "group-"; |
|||
|
|||
var tagHelperAttributes = output.Attributes.Where(a => !a.Name.StartsWith(groupPrefix)).ToList(); |
|||
|
|||
var attrList = new TagHelperAttributeList(); |
|||
|
|||
foreach (var tagHelperAttribute in tagHelperAttributes) |
|||
{ |
|||
attrList.Add(tagHelperAttribute); |
|||
} |
|||
|
|||
if (attrList.ContainsName("type")) |
|||
{ |
|||
attrList.Remove(attrList.First(a => a.Name == "type")); |
|||
} |
|||
|
|||
if (attrList.ContainsName("name")) |
|||
{ |
|||
attrList.Remove(attrList.First(a => a.Name == "name")); |
|||
} |
|||
|
|||
if (attrList.ContainsName("id")) |
|||
{ |
|||
attrList.Remove(attrList.First(a => a.Name == "id")); |
|||
} |
|||
|
|||
if (attrList.ContainsName("value")) |
|||
{ |
|||
attrList.Remove(attrList.First(a => a.Name == "value")); |
|||
} |
|||
|
|||
if (TagHelper.Locale != null) |
|||
{ |
|||
attrList.Add("data-locale", JsonSerializer.Serialize(TagHelper.Locale)); |
|||
} |
|||
|
|||
if (TagHelper.MinDate != null) |
|||
{ |
|||
attrList.Add("data-min-date", TagHelper.MinDate); |
|||
} |
|||
|
|||
if (TagHelper.MaxDate != null) |
|||
{ |
|||
attrList.Add("data-max-date", TagHelper.MaxDate); |
|||
} |
|||
|
|||
if (TagHelper.MaxSpan != null) |
|||
{ |
|||
attrList.Add("data-max-span", JsonSerializer.Serialize(TagHelper.MaxSpan)); |
|||
} |
|||
|
|||
if (TagHelper.ShowDropdowns == false) |
|||
{ |
|||
attrList.Add("data-show-dropdowns", TagHelper.ShowDropdowns.ToString().ToLowerInvariant()); |
|||
} |
|||
|
|||
if (TagHelper.MinYear != null) |
|||
{ |
|||
attrList.Add("data-min-year", TagHelper.MinYear); |
|||
} |
|||
|
|||
if (TagHelper.MaxYear != null) |
|||
{ |
|||
attrList.Add("data-max-year", TagHelper.MaxYear); |
|||
} |
|||
|
|||
switch (TagHelper.WeekNumbers) |
|||
{ |
|||
case AbpDatePickerWeekNumbers.Normal: |
|||
attrList.Add("data-show-week-numbers", "true"); |
|||
break; |
|||
case AbpDatePickerWeekNumbers.Iso: |
|||
attrList.Add("data-show-iso-week-numbers", "true"); |
|||
break; |
|||
} |
|||
|
|||
if (TagHelper.TimePicker != null) |
|||
{ |
|||
attrList.Add("data-time-picker", TagHelper.TimePicker.ToString().ToLowerInvariant()); |
|||
} |
|||
|
|||
if (TagHelper.TimePickerIncrement != null) |
|||
{ |
|||
attrList.Add("data-time-picker-increment", TagHelper.TimePickerIncrement); |
|||
} |
|||
|
|||
if (TagHelper.TimePicker24Hour != null) |
|||
{ |
|||
attrList.Add("data-time-picker24-hour", TagHelper.TimePicker24Hour.ToString().ToLowerInvariant()); |
|||
} |
|||
|
|||
if (TagHelper.TimePickerSeconds != null) |
|||
{ |
|||
attrList.Add("data-time-picker-seconds", TagHelper.TimePickerSeconds.ToString().ToLowerInvariant()); |
|||
} |
|||
|
|||
if (TagHelper.Opens != AbpDatePickerOpens.Center) |
|||
{ |
|||
attrList.Add("data-opens", TagHelper.Opens.ToString().ToLowerInvariant()); |
|||
} |
|||
|
|||
if (TagHelper.Drops != AbpDatePickerDrops.Down) |
|||
{ |
|||
attrList.Add("data-drops", TagHelper.Drops.ToString().ToLowerInvariant()); |
|||
} |
|||
|
|||
if (!TagHelper.ButtonClasses.IsNullOrEmpty()) |
|||
{ |
|||
attrList.Add("data-button-classes", TagHelper.ButtonClasses); |
|||
} |
|||
|
|||
if (!TagHelper.ApplyButtonClasses.IsNullOrEmpty()) |
|||
{ |
|||
attrList.Add("data-apply-button-classes", TagHelper.ApplyButtonClasses); |
|||
} |
|||
|
|||
if (!TagHelper.CancelButtonClasses.IsNullOrEmpty()) |
|||
{ |
|||
attrList.Add("data-cancel-button-classes", TagHelper.CancelButtonClasses); |
|||
} |
|||
|
|||
if (!TagHelper.AutoApply) |
|||
{ |
|||
attrList.Add("data-auto-apply", TagHelper.AutoApply.ToString().ToLowerInvariant()); |
|||
} |
|||
|
|||
if (TagHelper.LinkedCalendars != null) |
|||
{ |
|||
attrList.Add("data-linked-calendars", TagHelper.LinkedCalendars.ToString().ToLowerInvariant()); |
|||
} |
|||
|
|||
if (TagHelper.AutoUpdateInput) |
|||
{ |
|||
attrList.Add("data-auto-update-input", TagHelper.AutoUpdateInput.ToString().ToLowerInvariant()); |
|||
} |
|||
|
|||
if (!TagHelper.ParentEl.IsNullOrEmpty()) |
|||
{ |
|||
attrList.Add("data-parent-el", TagHelper.ParentEl); |
|||
} |
|||
|
|||
if (!TagHelper.DateFormat.IsNullOrEmpty()) |
|||
{ |
|||
attrList.Add("data-date-format", TagHelper.DateFormat); |
|||
} |
|||
|
|||
if(TagHelper.Ranges != null && TagHelper.Ranges.Any()) |
|||
{ |
|||
var ranges = TagHelper.Ranges.ToDictionary(r => r.Label, r => r.Dates); |
|||
|
|||
attrList.Add("data-ranges", JsonSerializer.Serialize(ranges)); |
|||
} |
|||
|
|||
if(TagHelper.AlwaysShowCalendars) |
|||
{ |
|||
attrList.Add("data-always-show-calendars", TagHelper.AlwaysShowCalendars.ToString().ToLowerInvariant()); |
|||
} |
|||
|
|||
if(TagHelper.ShowCustomRangeLabel == false) |
|||
{ |
|||
attrList.Add("data-show-custom-range-label", TagHelper.ShowCustomRangeLabel.ToString().ToLowerInvariant()); |
|||
} |
|||
|
|||
if(TagHelper.Options != null) |
|||
{ |
|||
attrList.Add("data-options", JsonSerializer.Serialize(TagHelper.Options)); |
|||
} |
|||
|
|||
if (TagHelper.IsUtc) |
|||
{ |
|||
attrList.Add("data-is-utc", "true"); |
|||
} |
|||
|
|||
if (TagHelper.IsIso) |
|||
{ |
|||
attrList.Add("data-is-iso", TagHelper.IsIso.ToString().ToLowerInvariant()); |
|||
} |
|||
|
|||
AddBaseTagAttributes(attrList); |
|||
|
|||
return attrList; |
|||
} |
|||
|
|||
protected virtual bool IsOutputHidden(TagHelperOutput inputTag) |
|||
{ |
|||
return inputTag.Attributes.Any(a => |
|||
a.Name.ToLowerInvariant() == "type" && a.Value?.ToString()?.ToLowerInvariant() == "hidden"); |
|||
} |
|||
|
|||
protected virtual string GetInfoAsHtml(TagHelperContext context, TagHelperOutput output, TagHelperOutput inputTag) |
|||
{ |
|||
if (IsOutputHidden(inputTag)) |
|||
{ |
|||
return string.Empty; |
|||
} |
|||
|
|||
string text; |
|||
ModelExplorer modelExplorer = null; |
|||
|
|||
if (!string.IsNullOrEmpty(TagHelper.InfoText)) |
|||
{ |
|||
text = TagHelper.InfoText; |
|||
} |
|||
else |
|||
{ |
|||
var infoAttribute = GetAttributeAndModelExpression<InputInfoText>(out var modelExpression); |
|||
if (infoAttribute != null) |
|||
{ |
|||
modelExplorer = modelExpression.ModelExplorer; |
|||
text = infoAttribute.Text; |
|||
} |
|||
else |
|||
{ |
|||
return string.Empty; |
|||
} |
|||
} |
|||
|
|||
var idAttr = inputTag.Attributes.FirstOrDefault(a => a.Name == "id"); |
|||
var localizedText = TagHelperLocalizer.GetLocalizedText(text, modelExplorer); |
|||
|
|||
var div = new TagBuilder("div"); |
|||
div.Attributes.Add("id", idAttr?.Value + "InfoText"); |
|||
div.AddCssClass("form-text"); |
|||
div.InnerHtml.Append(localizedText); |
|||
|
|||
inputTag.Attributes.Add("aria-describedby", idAttr?.Value + "InfoText"); |
|||
|
|||
return div.ToHtmlString(); |
|||
} |
|||
|
|||
protected virtual async Task<string> GetLabelAsHtmlAsync(TagHelperContext context, TagHelperOutput output, |
|||
TagHelperOutput inputTag) |
|||
{ |
|||
if (string.IsNullOrEmpty(TagHelper.Label)) |
|||
{ |
|||
return await GetLabelAsHtmlUsingTagHelperAsync(context, output) + GetRequiredSymbol(context, output); |
|||
} |
|||
|
|||
var label = new TagBuilder("label"); |
|||
label.Attributes.Add("for", GetIdAttributeValue(inputTag)); |
|||
label.InnerHtml.AppendHtml(TagHelper.Label); |
|||
|
|||
label.AddCssClass("form-label"); |
|||
|
|||
if (!TagHelper.LabelTooltip.IsNullOrEmpty()) |
|||
{ |
|||
label.Attributes.Add("data-bs-toggle", "tooltip"); |
|||
label.Attributes.Add("data-bs-placement", TagHelper.LabelTooltipPlacement); |
|||
if (TagHelper.LabelTooltipHtml) |
|||
{ |
|||
label.Attributes.Add("data-bs-html", "true"); |
|||
} |
|||
|
|||
label.Attributes.Add("title", TagHelper.LabelTooltip); |
|||
label.InnerHtml.AppendHtml($" <i class=\"bi {TagHelper.LabelTooltipIcon}\"></i>"); |
|||
} |
|||
|
|||
return label.ToHtmlString(); |
|||
} |
|||
|
|||
protected virtual string GetIdAttributeValue(TagHelperOutput inputTag) |
|||
{ |
|||
var idAttr = inputTag.Attributes.FirstOrDefault(a => a.Name == "id"); |
|||
|
|||
return idAttr != null ? idAttr.Value.ToString() : string.Empty; |
|||
} |
|||
|
|||
protected virtual string GetRequiredSymbol(TagHelperContext context, TagHelperOutput output) |
|||
{ |
|||
if (!TagHelper.DisplayRequiredSymbol) |
|||
{ |
|||
return ""; |
|||
} |
|||
|
|||
return GetAttribute<RequiredAttribute>() != null ? "<span> * </span>" : ""; |
|||
} |
|||
|
|||
protected abstract ModelExpression GetModelExpression(); |
|||
|
|||
protected virtual async Task<string> GetLabelAsHtmlUsingTagHelperAsync(TagHelperContext context, |
|||
TagHelperOutput output) |
|||
{ |
|||
var labelTagHelper = new LabelTagHelper(Generator) { |
|||
ViewContext = TagHelper.ViewContext, |
|||
For = GetModelExpression() |
|||
}; |
|||
|
|||
var attributeList = new TagHelperAttributeList(); |
|||
|
|||
attributeList.AddClass("form-label"); |
|||
|
|||
if (!TagHelper.LabelTooltip.IsNullOrEmpty()) |
|||
{ |
|||
attributeList.Add("data-bs-toggle", "tooltip"); |
|||
attributeList.Add("data-bs-placement", TagHelper.LabelTooltipPlacement); |
|||
if (TagHelper.LabelTooltipHtml) |
|||
{ |
|||
attributeList.Add("data-bs-html", "true"); |
|||
} |
|||
|
|||
attributeList.Add("title", TagHelper.LabelTooltip); |
|||
} |
|||
|
|||
var innerOutput = |
|||
await labelTagHelper.ProcessAndGetOutputAsync(attributeList, context, "label", TagMode.StartTagAndEndTag); |
|||
if (!TagHelper.LabelTooltip.IsNullOrEmpty()) |
|||
{ |
|||
innerOutput.Content.AppendHtml($" <i class=\"bi {TagHelper.LabelTooltipIcon}\"></i>"); |
|||
} |
|||
|
|||
return innerOutput.Render(Encoder); |
|||
} |
|||
|
|||
protected virtual async Task<string> ProcessButtonAndGetContentAsync(TagHelperContext context, |
|||
TagHelperOutput output, string icon, string type) |
|||
{ |
|||
var abpButtonTagHelper = ServiceProvider.GetRequiredService<AbpButtonTagHelper>(); |
|||
var attributes = |
|||
new TagHelperAttributeList { new("type", "button"), new("tabindex", "-1"), new("data-type", type) }; |
|||
abpButtonTagHelper.ButtonType = AbpButtonType.Outline_Secondary; |
|||
abpButtonTagHelper.Icon = icon; |
|||
|
|||
return await abpButtonTagHelper.RenderAsync(attributes, context, Encoder, "button", TagMode.StartTagAndEndTag); |
|||
} |
|||
|
|||
protected virtual void AddInfoTextId(TagHelperOutput inputTagHelperOutput) |
|||
{ |
|||
if (GetAttribute<InputInfoText>() == null) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
var idAttr = inputTagHelperOutput.Attributes.FirstOrDefault(a => a.Name == "id"); |
|||
|
|||
if (idAttr == null) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
inputTagHelperOutput.Attributes.Add("aria-describedby", GetInfoText()); |
|||
} |
|||
|
|||
public virtual string GetInfoText() |
|||
{ |
|||
var infoAttribute = GetAttributeAndModelExpression<InputInfoText>(out var modelExpression); |
|||
|
|||
if (infoAttribute != null) |
|||
{ |
|||
return TagHelperLocalizer.GetLocalizedText(infoAttribute.Text, modelExpression.ModelExplorer); |
|||
} |
|||
|
|||
return string.Empty; |
|||
} |
|||
|
|||
protected virtual void AddPlaceholderAttribute(TagHelperOutput inputTagHelperOutput) |
|||
{ |
|||
if (inputTagHelperOutput.Attributes.ContainsName("placeholder")) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
var attribute = GetAttributeAndModelExpression<Placeholder>(out var modelExpression); |
|||
|
|||
if (attribute != null) |
|||
{ |
|||
var placeholderLocalized = |
|||
TagHelperLocalizer.GetLocalizedText(attribute.Value, modelExpression.ModelExplorer); |
|||
|
|||
inputTagHelperOutput.Attributes.Add("placeholder", placeholderLocalized); |
|||
} |
|||
} |
|||
|
|||
protected virtual void AddFormControls(TagHelperContext context, TagHelperOutput output, |
|||
TagHelperOutput inputTagHelperOutput) |
|||
{ |
|||
inputTagHelperOutput.Attributes.AddClass("form-control"); |
|||
var size = GetSize(context, output); |
|||
if (!size.IsNullOrEmpty()) |
|||
{ |
|||
inputTagHelperOutput.Attributes.AddClass(size); |
|||
} |
|||
} |
|||
|
|||
protected virtual void AddAutoFocusAttribute(TagHelperOutput inputTagHelperOutput) |
|||
{ |
|||
if (TagHelper.AutoFocus && !inputTagHelperOutput.Attributes.ContainsName("data-auto-focus")) |
|||
{ |
|||
inputTagHelperOutput.Attributes.Add("data-auto-focus", "true"); |
|||
} |
|||
} |
|||
|
|||
protected virtual void AddDisabledAttribute(TagHelperOutput inputTagHelperOutput) |
|||
{ |
|||
if (inputTagHelperOutput.Attributes.ContainsName("disabled") == false && |
|||
(TagHelper.IsDisabled || GetAttribute<DisabledInput>() != null)) |
|||
{ |
|||
inputTagHelperOutput.Attributes.Add("disabled", ""); |
|||
} |
|||
} |
|||
|
|||
|
|||
protected virtual string GetSize(TagHelperContext context, TagHelperOutput output) |
|||
{ |
|||
// TODO: Test this method
|
|||
var attribute = GetAttribute<FormControlSize>(); |
|||
|
|||
if (attribute != null) |
|||
{ |
|||
TagHelper.Size = attribute.Size; |
|||
} |
|||
|
|||
return TagHelper.Size switch { |
|||
AbpFormControlSize.Small => "form-control-sm", |
|||
AbpFormControlSize.Medium => "form-control-md", |
|||
AbpFormControlSize.Large => "form-control-lg", |
|||
_ => "" |
|||
}; |
|||
} |
|||
|
|||
protected abstract Task<string> GetValidationAsHtmlAsync(TagHelperContext context, TagHelperOutput output); |
|||
|
|||
protected virtual async Task<string> GetValidationAsHtmlByInputAsync(TagHelperContext context, |
|||
TagHelperOutput output, |
|||
[NotNull]InputTagHelper inputTag) |
|||
{ |
|||
var validationMessageTagHelper = |
|||
new ValidationMessageTagHelper(Generator) { For = inputTag.For, ViewContext = TagHelper.ViewContext }; |
|||
|
|||
var attributeList = new TagHelperAttributeList { { "class", "text-danger col-auto" } }; |
|||
|
|||
return await validationMessageTagHelper.RenderAsync(attributeList, context, Encoder, "span", |
|||
TagMode.StartTagAndEndTag); |
|||
} |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.DatePicker; |
|||
|
|||
public enum AbpDatePickerDrops |
|||
{ |
|||
Down, |
|||
Up, |
|||
Auto |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.DatePicker; |
|||
|
|||
public enum AbpDatePickerOpens |
|||
{ |
|||
Left, |
|||
Right, |
|||
Center |
|||
} |
|||
@ -0,0 +1,47 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
|
|||
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.DatePicker; |
|||
|
|||
public class AbpDatePickerRange |
|||
{ |
|||
private readonly List<string> _dates = new List<string>(); |
|||
public string Label { get; set; } |
|||
public IReadOnlyList<string> Dates => _dates; |
|||
|
|||
public void AddDate(string date) |
|||
{ |
|||
_dates.Add(DateTime.Parse(date).ToString("O")); |
|||
} |
|||
|
|||
public void AddDate(DateTime date) |
|||
{ |
|||
_dates.Add(date.ToString("O")); |
|||
} |
|||
|
|||
public void AddDate(DateTimeOffset date) |
|||
{ |
|||
_dates.Add(date.ToString("O")); |
|||
} |
|||
|
|||
public void AddDate(DateTime? date) |
|||
{ |
|||
if (date.HasValue) |
|||
{ |
|||
_dates.Add(date.Value.ToString("O")); |
|||
} |
|||
} |
|||
|
|||
public void AddDate(DateTimeOffset? date) |
|||
{ |
|||
if (date.HasValue) |
|||
{ |
|||
_dates.Add(date.Value.ToString("O")); |
|||
} |
|||
} |
|||
|
|||
public void AddDate(string date, string format) |
|||
{ |
|||
_dates.Add(DateTime.ParseExact(date, format, null).ToString("O")); |
|||
} |
|||
} |
|||
@ -0,0 +1,8 @@ |
|||
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.DatePicker; |
|||
|
|||
public enum AbpDatePickerWeekNumbers |
|||
{ |
|||
None, |
|||
Normal, |
|||
Iso |
|||
} |
|||
Loading…
Reference in new issue