Browse Source

Merge pull request #5331 from SecTex/SecTex/html-encoding

Use IHtmlGenerator / TagBuilder in all necessary tag helpers
pull/5659/head
Yunus Emre Kalkan 6 years ago
committed by GitHub
parent
commit
e07e3a3234
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 13
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/AbpTagHelperService.cs
  2. 19
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Breadcrumb/AbpBreadcrumbItemTagHelperService.cs
  3. 32
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Breadcrumb/AbpBreadcrumbTagHelperService.cs
  4. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonTagHelper.cs
  5. 16
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonTagHelperService.cs
  6. 11
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonTagHelperServiceBase.cs
  7. 32
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Carousel/AbpCarouselItemTagHelperService.cs
  8. 97
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Carousel/AbpCarouselTagHelperService.cs
  9. 50
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpAccordionItemTagHelperService.cs
  10. 35
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpAccordionTagHelperService.cs
  11. 43
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelperService.cs
  12. 42
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpRadioInputTagHelperService.cs
  13. 45
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelperService.cs
  14. 162
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Modal/AbpModalFooterTagHelperService.cs
  15. 38
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Modal/AbpModalHeaderTagHelperService.cs
  16. 87
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Modal/AbpModalTagHelperService.cs
  17. 30
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Nav/AbpNavbarToggleTagHelperService.cs
  18. 16
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Pagination/AbpPaginationTagHelperService.cs
  19. 58
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Popover/AbpPopoverTagHelperService.cs
  20. 35
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Tab/AbpTabDropdownTagHelperService.cs
  21. 33
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Tab/AbpTabLinkTagHelperService.cs
  22. 74
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Tab/AbpTabTagHelperService.cs
  23. 46
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Tab/AbpTabsTagHelperService.cs
  24. 23
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/TagBuilderExtensions.cs
  25. 18
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Tooltip/AbpTooltipTagHelperService.cs
  26. 12
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-extensions.js
  27. 7
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/jquery/jquery-extensions.js
  28. 3
      framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Buttons.cshtml
  29. 32
      framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Carousel.cshtml

13
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/AbpTagHelperService.cs

@ -1,14 +1,5 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form;
using Volo.Abp.Threading;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers
{
@ -52,4 +43,4 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers
return Task.CompletedTask;
}
}
}
}

19
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Breadcrumb/AbpBreadcrumbItemTagHelperService.cs

@ -1,6 +1,7 @@
using System.Collections.Generic;
using System.Text.Encodings.Web;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Razor.TagHelpers;
using System.Collections.Generic;
using System.Text.Encodings.Web;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions;
@ -14,6 +15,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Breadcrumb
{
_encoder = encoder;
}
public override void Process(TagHelperContext context, TagHelperOutput output)
{
output.TagName = "li";
@ -24,7 +26,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Breadcrumb
var list = context.GetValue<List<BreadcrumbItem>>(BreadcrumbItemsContent);
output.Content.SetHtmlContent(GetInnerHtml(context, output));
list.Add(new BreadcrumbItem
{
Html = output.Render(_encoder),
@ -39,10 +41,13 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Breadcrumb
if (string.IsNullOrWhiteSpace(TagHelper.Href))
{
output.Attributes.Add("aria-current", "page");
return TagHelper.Title;
return _encoder.Encode(TagHelper.Title);
}
return "<a href=\"" + TagHelper.Href + "\">" + TagHelper.Title + "</a>";
}
var link = new TagBuilder("a");
link.Attributes.Add("href", TagHelper.Href);
link.InnerHtml.Append(TagHelper.Title);
return link.ToHtmlString();
}
}
}
}

32
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Breadcrumb/AbpBreadcrumbTagHelperService.cs

@ -1,8 +1,8 @@
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Razor.TagHelpers;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.TagHelpers;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Breadcrumb
{
@ -10,37 +10,37 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Breadcrumb
{
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
output.TagName = "nav";
output.Attributes.Add("aria-label", "breadcrumb");
var list = InitilizeFormGroupContentsContext(context, output);
await output.GetChildContentAsync();
SetInnerOlTag(context, output);
SetInnerList(context, output, list);
var listTagBuilder = GetOlTagBuilder();
output.TagName = "nav";
output.Attributes.Add("aria-label", "breadcrumb");
SetInnerList(context, output, list, listTagBuilder);
output.Content.SetHtmlContent(listTagBuilder);
}
protected virtual void SetInnerOlTag(TagHelperContext context, TagHelperOutput output)
protected virtual TagBuilder GetOlTagBuilder()
{
output.PreContent.SetHtmlContent("<ol class=\"breadcrumb\">");
output.PostContent.SetHtmlContent("</ol>");
var builder = new TagBuilder("ol");
builder.AddCssClass("breadcrumb");
return builder;
}
protected virtual void SetInnerList(TagHelperContext context, TagHelperOutput output, List<BreadcrumbItem> list)
protected virtual void SetInnerList(TagHelperContext context, TagHelperOutput output, List<BreadcrumbItem> list, TagBuilder listTagBuilder)
{
SetLastOneActiveIfThereIsNotAny(context, output, list);
var html = new StringBuilder("");
foreach (var breadcrumbItem in list)
{
var htmlPart = SetActiveClassIfActiveAndGetHtml(breadcrumbItem);
html.AppendLine(htmlPart);
listTagBuilder.InnerHtml.AppendHtml(htmlPart);
}
output.Content.SetHtmlContent(html.ToString());
}
protected virtual List<BreadcrumbItem> InitilizeFormGroupContentsContext(TagHelperContext context, TagHelperOutput output)

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonTagHelper.cs

@ -19,6 +19,8 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button
public FontIconType IconType { get; set; } = FontIconType.FontAwesome;
public bool BusyTextIsHtml { get; set; }
public AbpButtonTagHelper(AbpButtonTagHelperService service)
: base(service)
{

16
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonTagHelperService.cs

@ -1,13 +1,14 @@
using System;
using Localization.Resources.AbpUi;
using Localization.Resources.AbpUi;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.Extensions.Localization;
using System;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button
{
public class AbpButtonTagHelperService : AbpButtonTagHelperServiceBase<AbpButtonTagHelper>
{
protected const string DataBusyTextAttributeName = "data-busy-text";
protected const string DataBusyTextIsHtmlAttributeName = "data-busy-text-is-html";
protected IStringLocalizer<AbpUiResource> L { get; }
@ -22,6 +23,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button
output.TagName = "button";
AddType(context, output);
AddBusyText(context, output);
AddBusyTextIsHtml(context, output);
}
protected virtual void AddType(TagHelperContext context, TagHelperOutput output)
@ -44,5 +46,15 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button
output.Attributes.SetAttribute(DataBusyTextAttributeName, busyText);
}
protected virtual void AddBusyTextIsHtml(TagHelperContext context, TagHelperOutput output)
{
if (!TagHelper.BusyTextIsHtml)
{
return;
}
output.Attributes.SetAttribute(DataBusyTextIsHtmlAttributeName, TagHelper.BusyTextIsHtml.ToString().ToLower());
}
}
}

11
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Button/AbpButtonTagHelperServiceBase.cs

@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Razor.TagHelpers;
using System;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers;
@ -43,7 +44,9 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button
return;
}
output.Content.AppendHtml($"<i class=\"{GetIconClass(context, output)}\"></i> ");
var icon = new TagBuilder("i");
icon.AddCssClass(GetIconClass(context, output));
output.Content.AppendHtml(icon);
}
protected virtual string GetIconClass(TagHelperContext context, TagHelperOutput output)
@ -64,7 +67,9 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Button
return;
}
output.Content.AppendHtml($"<span>{TagHelper.Text}</span>");
var span = new TagBuilder("span");
span.InnerHtml.Append(TagHelper.Text);
output.Content.AppendHtml(span);
}
protected virtual void AddDisabled(TagHelperContext context, TagHelperOutput output)

32
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Carousel/AbpCarouselItemTagHelperService.cs

@ -1,7 +1,7 @@
using System.Collections.Generic;
using System.Text;
using System.Text.Encodings.Web;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Razor.TagHelpers;
using System.Collections.Generic;
using System.Text.Encodings.Web;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions;
@ -42,8 +42,12 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Carousel
protected virtual void SetInnerImgTag(TagHelperContext context, TagHelperOutput output)
{
var imgTag ="<img class=\"d-block w-100\" src=\""+TagHelper.Src+ "\" alt=\"" + TagHelper.Alt + "\">";
output.Content.SetHtmlContent(imgTag);
var img = new TagBuilder("img");
img.AddCssClass("d-block w-100");
img.Attributes.Add("src", TagHelper.Src);
img.Attributes.Add("alt", TagHelper.Alt);
output.Content.SetHtmlContent(img);
}
protected virtual void SetActive(TagHelperContext context, TagHelperOutput output)
@ -61,15 +65,19 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Carousel
return;
}
var html = new StringBuilder("");
var title = new TagBuilder("h5");
title.InnerHtml.Append(TagHelper.CaptionTitle);
var caption = new TagBuilder("p");
caption.InnerHtml.Append(TagHelper.Caption);
html.AppendLine("<div class=\"carousel-caption d-none d-md-block\">");
html.AppendLine("<h5>"+TagHelper.CaptionTitle+"</h5>");
html.AppendLine("<p>" + TagHelper.Caption + "</p>");
html.AppendLine("</div>");
var wrapper = new TagBuilder("div");
wrapper.AddCssClass("carousel-caption d-none d-md-block");
wrapper.InnerHtml.AppendHtml(title);
wrapper.InnerHtml.AppendHtml(caption);
output.PostContent.SetHtmlContent(html.ToString());
output.PostContent.SetHtmlContent(wrapper);
}
}
}
}

97
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Carousel/AbpCarouselTagHelperService.cs

@ -1,15 +1,24 @@
using System;
using Localization.Resources.AbpUi;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.Extensions.Localization;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Carousel
{
public class AbpCarouselTagHelperService : AbpTagHelperService<AbpCarouselTagHelper>
{
protected IStringLocalizer<AbpUiResource> L { get; }
public AbpCarouselTagHelperService(IStringLocalizer<AbpUiResource> localizer)
{
L = localizer;
}
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
output.TagName = "div";
@ -37,18 +46,17 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Carousel
protected virtual void SetItems(TagHelperContext context, TagHelperOutput output, List<CarouselItem> itemList)
{
var itemsHtml = new StringBuilder("");
itemsHtml.Append("<div class= \"carousel-inner\">");
var wrapper = new TagBuilder("div");
wrapper.AddCssClass("carousel-inner");
foreach (var carouselItem in itemList)
{
SetActiveIfActive(carouselItem);
itemsHtml.AppendLine(carouselItem.Html);
wrapper.InnerHtml.AppendHtml(carouselItem.Html);
}
itemsHtml.Append("</div>");
output.Content.SetHtmlContent(itemsHtml.ToString());
output.Content.SetHtmlContent(wrapper);
}
protected virtual void SetControls(TagHelperContext context, TagHelperOutput output, List<CarouselItem> itemList)
@ -58,18 +66,45 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Carousel
return;
}
var html = new StringBuilder("");
html.AppendLine("<a class=\"carousel-control-prev\" href=\"#" + TagHelper.Id + "\" role=\"button\" data-slide=\"prev\">");
html.AppendLine("<span class=\"carousel-control-prev-icon\" aria-hidden=\"true\"></span>");
html.AppendLine("<span class=\"sr-only\">Previous</span>");
html.AppendLine("</a>");
html.AppendLine("<a class=\"carousel-control-next\" href=\"#" + TagHelper.Id + "\" role=\"button\" data-slide=\"next\">");
html.AppendLine("<span class=\"carousel-control-next-icon\" aria-hidden=\"true\"></span>");
html.AppendLine("<span class=\"sr-only\">Next</span>");
html.AppendLine("</a>");
output.PostContent.SetHtmlContent(html.ToString());
// create 'previous' item
var prevIcon = new TagBuilder("span");
prevIcon.AddCssClass("carousel-control-prev-icon");
prevIcon.Attributes.Add("aria-hidden", "true");
var prevText = new TagBuilder("span");
prevText.AddCssClass("sr-only");
prevText.InnerHtml.Append(L["Previous"].Value);
var prevAnchor = new TagBuilder("a");
prevAnchor.AddCssClass("carousel-control-prev");
prevAnchor.Attributes.Add("href", "#" + TagHelper.Id);
prevAnchor.Attributes.Add("role", "button");
prevAnchor.Attributes.Add("data-slide", "prev");
prevAnchor.InnerHtml.AppendHtml(prevIcon);
prevAnchor.InnerHtml.AppendHtml(prevText);
// create 'next' item
var nextIcon = new TagBuilder("span");
nextIcon.AddCssClass("carousel-control-next-icon");
nextIcon.Attributes.Add("aria-hidden", "true");
var nextText = new TagBuilder("span");
nextText.AddCssClass("sr-only");
nextText.InnerHtml.Append(L["Next"].Value);
var nextAnchor = new TagBuilder("a");
nextAnchor.AddCssClass("carousel-control-next");
nextAnchor.Attributes.Add("href", "#" + TagHelper.Id);
nextAnchor.Attributes.Add("role", "button");
nextAnchor.Attributes.Add("data-slide", "next");
nextAnchor.InnerHtml.AppendHtml(nextIcon);
nextAnchor.InnerHtml.AppendHtml(nextText);
// append post content
output.PostContent.AppendHtml(prevAnchor);
output.PostContent.AppendHtml(nextAnchor);
}
protected virtual void SetIndicators(TagHelperContext context, TagHelperOutput output, List<CarouselItem> itemList)
@ -79,20 +114,24 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Carousel
return;
}
var html = new StringBuilder("<ol class=\"carousel-indicators\">");
var list = new TagBuilder("ol");
list.AddCssClass("carousel-indicators");
for (var i = 0; i < itemList.Count; i++)
{
html.AppendLine(
"<li " +
"data-target=\"#" + TagHelper.Id + "\"" +
" data-slide-to=\"" + i + "\"" +
(itemList[i].Active ? " class=\"active\">" : "") +
"</li>");
var listItem = new TagBuilder("li");
listItem.Attributes.Add("data-target", "#" + TagHelper.Id);
listItem.Attributes.Add("data-slide-to", i.ToString());
if (itemList[i].Active)
{
listItem.AddCssClass("active");
}
list.InnerHtml.AppendHtml(listItem);
}
html.AppendLine("</ol>");
output.PreContent.SetHtmlContent(html.ToString());
output.PreContent.SetHtmlContent(list);
}
protected virtual void SetOneItemAsActive(TagHelperContext context, TagHelperOutput output, List<CarouselItem> itemList)

50
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpAccordionItemTagHelperService.cs

@ -1,7 +1,8 @@
using System;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Razor.TagHelpers;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Collapse
@ -17,7 +18,6 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Collapse
var html = GetAccordionHeaderItem(context, output) + GetAccordionContentItem(context, output, innerContent);
var tabHeaderItems = context.GetValue<List<string>>(AccordionItems);
tabHeaderItems.Add(html);
output.SuppressOutput();
@ -25,23 +25,43 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Collapse
protected virtual string GetAccordionHeaderItem(TagHelperContext context, TagHelperOutput output)
{
return " <div class=\"card-header\" id=\"" + GetHeadingId() + "\">" + Environment.NewLine +
" <h5 class=\"mb-0\">" + Environment.NewLine +
" <button class=\"btn btn-link\" type=\"button\" data-toggle=\"collapse\" data-target=\"#" + GetContentId() + "\" aria-expanded=\"true\" aria-controls=\"" + GetContentId() + "\">" + Environment.NewLine +
TagHelper.Title + Environment.NewLine +
" </button>" + Environment.NewLine +
" </h5>" + Environment.NewLine +
" </div>" + Environment.NewLine;
var button = new TagBuilder("button");
button.AddCssClass("btn btn-link");
button.Attributes.Add("type", "button");
button.Attributes.Add("data-toggle", "collapse");
button.Attributes.Add("data-target", "#" + GetContentId());
button.Attributes.Add("aria-expanded", "true");
button.Attributes.Add("aria-controls", GetContentId());
button.InnerHtml.Append(TagHelper.Title);
var h5 = new TagBuilder("h5");
h5.AddCssClass("mb-0");
h5.InnerHtml.AppendHtml(button);
var header = new TagBuilder("div");
header.AddCssClass("card-header");
header.Attributes.Add("id", GetHeadingId());
header.InnerHtml.AppendHtml(h5);
return header.ToHtmlString();
}
protected virtual string GetAccordionContentItem(TagHelperContext context, TagHelperOutput output, string content)
{
var show = (TagHelper.Active ?? false) ? " show" : "";
return "<div id=\"" + GetContentId() + "\" class=\"collapse"+ show + "\" aria-labelledby=\"" + GetHeadingId() + "\" data-parent=\"#" + AbpAccordionParentIdPlaceholder + "\">" + Environment.NewLine +
" <div class=\"card-body\">" + Environment.NewLine +
content + Environment.NewLine +
" </div>" + Environment.NewLine +
"</div>" + Environment.NewLine;
var cardBody = new TagBuilder("div");
cardBody.AddCssClass("card-body");
cardBody.InnerHtml.AppendHtml(content);
var wrapper = new TagBuilder("div");
wrapper.AddCssClass("collapse" + show);
wrapper.Attributes.Add("id", GetContentId());
wrapper.Attributes.Add("aria-labelledby", GetHeadingId());
wrapper.Attributes.Add("data-parent", "#" + AbpAccordionParentIdPlaceholder);
wrapper.InnerHtml.AppendHtml(cardBody);
return wrapper.ToHtmlString();
}
protected virtual string GetHeadingId()

35
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Collapse/AbpAccordionTagHelperService.cs

@ -1,14 +1,22 @@
using System;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Collapse
{
public class AbpAccordionTagHelperService : AbpTagHelperService<AbpAccordionTagHelper>
{
protected IHtmlGenerator HtmlGenerator { get; }
public AbpAccordionTagHelperService(IHtmlGenerator htmlGenerator)
{
HtmlGenerator = htmlGenerator;
}
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
SetRandomIdIfNotProvided();
@ -22,26 +30,21 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Collapse
await output.GetChildContentAsync();
var content = GetContent(items);
output.Content.SetHtmlContent(content);
SetContent(context, output, items);
}
protected virtual string GetContent(List<string> items)
protected virtual void SetContent(TagHelperContext context, TagHelperOutput output, List<string> items)
{
var html = new StringBuilder("");
foreach (var item in items)
{
var content = item.Replace(AbpAccordionParentIdPlaceholder, TagHelper.Id);
var content = item.Replace(AbpAccordionParentIdPlaceholder, HtmlGenerator.Encode(TagHelper.Id));
html.AppendLine(
"<div class=\"card\">" + Environment.NewLine +
content
+ "</div>" + Environment.NewLine
);
}
var wrapper = new TagBuilder("div");
wrapper.AddCssClass("card");
wrapper.InnerHtml.AppendHtml(content);
return html.ToString();
output.Content.AppendHtml(wrapper);
}
}
protected virtual List<string> InitilizeFormGroupContentsContext(TagHelperContext context, TagHelperOutput output)

43
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpInputTagHelperService.cs

@ -1,12 +1,13 @@
using System;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.TagHelpers;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.TagHelpers;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions;
@ -249,7 +250,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
{
if (IsOutputHidden(inputTag) || TagHelper.SuppressLabel)
{
return "";
return string.Empty;
}
if (string.IsNullOrEmpty(TagHelper.Label))
@ -257,11 +258,16 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
return await GetLabelAsHtmlUsingTagHelperAsync(context, output, isCheckbox) + GetRequiredSymbol(context, output);
}
var checkboxClass = isCheckbox ? "class=\"custom-control-label\" " : "";
var label = new TagBuilder("label");
label.Attributes.Add("for", GetIdAttributeValue(inputTag));
label.InnerHtml.Append(TagHelper.Label);
if (isCheckbox)
{
label.AddCssClass("custom-control-label");
}
return "<label " + checkboxClass + GetIdAttributeAsString(inputTag) + ">"
+ TagHelper.Label +
"</label>" + GetRequiredSymbol(context, output);
return label.ToHtmlString();
}
protected virtual string GetRequiredSymbol(TagHelperContext context, TagHelperOutput output)
@ -308,9 +314,11 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
var idAttr = inputTag.Attributes.FirstOrDefault(a => a.Name == "id");
var localizedText = _tagHelperLocalizer.GetLocalizedText(text, TagHelper.AspFor.ModelExplorer);
return "<small id=\"" + idAttr?.Value + "InfoText\" class=\"form-text text-muted\">" +
localizedText +
"</small>";
var small = new TagBuilder("small");
small.Attributes.Add("id", idAttr?.Value?.ToString() + "InfoText");
small.AddCssClass("form-text text-muted");
return small.ToHtmlString();
}
protected virtual async Task<string> GetLabelAsHtmlUsingTagHelperAsync(TagHelperContext context, TagHelperOutput output, bool isCheckbox)
@ -426,11 +434,18 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
return inputTag.Attributes.Any(a => a.Name.ToLowerInvariant() == "type" && a.Value.ToString().ToLowerInvariant() == "hidden");
}
protected virtual string GetIdAttributeAsString(TagHelperOutput inputTag)
protected virtual string GetIdAttributeValue(TagHelperOutput inputTag)
{
var idAttr = inputTag.Attributes.FirstOrDefault(a => a.Name == "id");
return idAttr != null ? "for=\"" + idAttr.Value + "\"" : "";
return idAttr != null ? idAttr.Value.ToString() : string.Empty;
}
protected virtual string GetIdAttributeAsString(TagHelperOutput inputTag)
{
var id = GetIdAttributeValue(inputTag);
return !string.IsNullOrWhiteSpace(id) ? "for=\"" + id + "\"" : string.Empty;
}
protected virtual void AddGroupToFormGroupContents(TagHelperContext context, string propertyName, string html, int order, out bool suppress)

42
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpRadioInputTagHelperService.cs

@ -1,12 +1,12 @@
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.Extensions.Localization;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.Extensions.Localization;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
@ -53,15 +53,35 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
var inlineClass = (TagHelper.Inline ?? false) ? " custom-control-inline" : "";
var id = TagHelper.AspFor.Name + "Radio" + selectItem.Value;
var name = TagHelper.AspFor.Name;
var selected = selectItem.Selected ? " checked=\"checked\"" : "";
var disabled = (TagHelper.Disabled??false) ? " disabled" : "";
var htmlPart = "<div class=\"custom-control custom-radio" + inlineClass + "\">\r\n" +
" <input type=\"radio\" id=\"" + id + "\" name=\"" + name + "\" value=\"" + selectItem.Value + "\"" + selected + " class=\"custom-control-input\""+ disabled + ">\r\n" +
" <label class=\"custom-control-label\" for=\"" + id + "\">" + selectItem.Text + "</label>\r\n" +
"</div>";
var input = new TagBuilder("input");
input.AddCssClass("custom-control-input");
input.Attributes.Add("type", "radio");
input.Attributes.Add("id", id);
input.Attributes.Add("name", name);
input.Attributes.Add("value", selectItem.Value);
if (selectItem.Selected)
{
input.Attributes.Add("checked", "checked");
}
if (TagHelper.Disabled ?? false)
{
input.Attributes.Add("disabled", "disabled");
}
var label = new TagBuilder("label");
label.AddCssClass("custom-control-label");
label.Attributes.Add("for", id);
label.InnerHtml.Append(selectItem.Text);
var wrapper = new TagBuilder("div");
wrapper.AddCssClass("custom-control custom-radio" + inlineClass);
wrapper.InnerHtml.AppendHtml(input);
wrapper.InnerHtml.AppendHtml(label);
html.AppendLine(htmlPart);
html.AppendLine(wrapper.ToHtmlString());
}
return html.ToString();

45
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelperService.cs

@ -1,20 +1,18 @@
using System;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.TagHelpers;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.Extensions.Localization;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.TagHelpers;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.Extensions.Localization;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions;
using Volo.Abp.DynamicProxy;
using Volo.Abp.Localization;
using Volo.Abp.Reflection;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
{
@ -26,9 +24,9 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
private readonly IStringLocalizerFactory _stringLocalizerFactory;
public AbpSelectTagHelperService(
IHtmlGenerator generator,
HtmlEncoder encoder,
IAbpTagHelperLocalizer tagHelperLocalizer,
IHtmlGenerator generator,
HtmlEncoder encoder,
IAbpTagHelperLocalizer tagHelperLocalizer,
IStringLocalizerFactory stringLocalizerFactory)
{
_generator = generator;
@ -140,7 +138,11 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
{
if (!string.IsNullOrEmpty(TagHelper.Label))
{
return "<label " + GetIdAttributeAsString(selectTag) + ">" + TagHelper.Label + "</label>" + GetRequiredSymbol(context, output);
var label = new TagBuilder("label");
label.Attributes.Add("for", GetIdAttributeValue(selectTag));
label.InnerHtml.Append(TagHelper.Label);
return label.ToHtmlString() + GetRequiredSymbol(context, output);
}
return await GetLabelAsHtmlUsingTagHelperAsync(context, output) + GetRequiredSymbol(context, output);
@ -199,9 +201,11 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
var idAttr = inputTag.Attributes.FirstOrDefault(a => a.Name == "id");
var localizedText = _tagHelperLocalizer.GetLocalizedText(text, TagHelper.AspFor.ModelExplorer);
return "<small id=\"" + idAttr?.Value + "InfoText\" class=\"form-text text-muted\">" +
localizedText +
"</small>";
var small = new TagBuilder("small");
small.Attributes.Add("id", idAttr?.Value?.ToString() + "InfoText");
small.AddCssClass("form-text text-muted");
return small.ToHtmlString();
}
protected virtual List<SelectListItem> GetSelectItemsFromEnum(TagHelperContext context, TagHelperOutput output, ModelExplorer explorer)
@ -338,11 +342,18 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Form
}
}
protected virtual string GetIdAttributeAsString(TagHelperOutput inputTag)
protected virtual string GetIdAttributeValue(TagHelperOutput inputTag)
{
var idAttr = inputTag.Attributes.FirstOrDefault(a => a.Name == "id");
return idAttr != null ? "for=\"" + idAttr.Value + "\"" : "";
return idAttr != null ? idAttr.Value.ToString() : string.Empty;
}
protected virtual string GetIdAttributeAsString(TagHelperOutput inputTag)
{
var id = GetIdAttributeValue(inputTag);
return !string.IsNullOrWhiteSpace(id) ? "for=\"" + id + "\"" : string.Empty;
}
protected virtual void AddGroupToFormGroupContents(TagHelperContext context, string propertyName, string html, int order, out bool suppress)

162
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Modal/AbpModalFooterTagHelperService.cs

@ -1,60 +1,106 @@
using System.Text;
using Localization.Resources.AbpUi;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.Extensions.Localization;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal
{
public class AbpModalFooterTagHelperService : AbpTagHelperService<AbpModalFooterTagHelper>
{
private readonly IStringLocalizer<AbpUiResource> _localizer;
public AbpModalFooterTagHelperService(IStringLocalizer<AbpUiResource> localizer)
{
_localizer = localizer;
}
public override void Process(TagHelperContext context, TagHelperOutput output)
{
output.TagName = "div";
output.Attributes.AddClass("modal-footer");
if (TagHelper.Buttons != AbpModalButtons.None)
{
output.PostContent.SetHtmlContent(CreateContent());
}
ProcessButtonsAlignment(output);
}
protected virtual string CreateContent()
{
var sb = new StringBuilder();
switch (TagHelper.Buttons)
{
case AbpModalButtons.Cancel:
sb.AppendLine("<button type=\"button\" class=\"btn btn-secondary\" data-dismiss=\"modal\">" + _localizer["Cancel"] + "</button>");
break;
case AbpModalButtons.Close:
sb.AppendLine("<button type=\"button\" class=\"btn btn-secondary\" data-dismiss=\"modal\">" + _localizer["Close"] + "</button>");
break;
case AbpModalButtons.Save:
sb.AppendLine("<button type=\"submit\" class=\"btn btn-primary\" data-busy-text=\"" + _localizer["SavingWithThreeDot"] + "\"><i class=\"fa fa-check\"></i> <span>" + _localizer["Save"] + "</span></button>");
break;
case AbpModalButtons.Save | AbpModalButtons.Cancel:
sb.AppendLine("<button type=\"button\" class=\"btn btn-secondary\" data-dismiss=\"modal\">" + _localizer["Cancel"] + "</button>");
sb.AppendLine("<button type=\"submit\" class=\"btn btn-primary\" data-busy-text=\"" + _localizer["SavingWithThreeDot"] + "\"><i class=\"fa fa-check\"></i> <span>" + _localizer["Save"] + "</span></button>");
break;
case AbpModalButtons.Save | AbpModalButtons.Close:
sb.AppendLine("<button type=\"button\" class=\"btn btn-secondary\" data-dismiss=\"modal\">" + _localizer["Close"] + "</button>");
sb.AppendLine("<button type=\"submit\" class=\"btn btn-primary\" data-busy-text=\"" + _localizer["SavingWithThreeDot"] + "\"><i class=\"fa fa-check\"></i> <span>" + _localizer["Save"] + "</span></button>");
break;
using Localization.Resources.AbpUi;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.Extensions.Localization;
using System.Text;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal
{
public class AbpModalFooterTagHelperService : AbpTagHelperService<AbpModalFooterTagHelper>
{
private readonly IStringLocalizer<AbpUiResource> _localizer;
public AbpModalFooterTagHelperService(IStringLocalizer<AbpUiResource> localizer)
{
_localizer = localizer;
}
public override void Process(TagHelperContext context, TagHelperOutput output)
{
output.TagName = "div";
output.Attributes.AddClass("modal-footer");
if (TagHelper.Buttons != AbpModalButtons.None)
{
output.PostContent.SetHtmlContent(CreateContent());
}
ProcessButtonsAlignment(output);
}
protected virtual string CreateContent()
{
var sb = new StringBuilder();
switch (TagHelper.Buttons)
{
case AbpModalButtons.Cancel:
sb.AppendLine(GetCancelButton());
break;
case AbpModalButtons.Close:
sb.AppendLine(GetCloseButton());
break;
case AbpModalButtons.Save:
sb.AppendLine(GetSaveButton());
break;
case AbpModalButtons.Save | AbpModalButtons.Cancel:
sb.AppendLine(GetSaveButton());
sb.AppendLine(GetCancelButton());
break;
case AbpModalButtons.Save | AbpModalButtons.Close:
sb.AppendLine(GetSaveButton());
sb.AppendLine(GetCloseButton());
break;
}
return sb.ToString();
}
return sb.ToString();
}
protected virtual string GetSaveButton()
{
var icon = new TagBuilder("i");
icon.AddCssClass("fa");
icon.AddCssClass("fa-check");
var span = new TagBuilder("span");
span.InnerHtml.Append(_localizer["Save"]);
var element = new TagBuilder("button");
element.Attributes.Add("type", "submit");
element.AddCssClass("btn");
element.AddCssClass("btn-primary");
element.Attributes.Add("data-busy-text", _localizer["SavingWithThreeDot"]);
element.InnerHtml.AppendHtml(icon);
element.InnerHtml.AppendHtml(span);
return element.ToHtmlString();
}
protected virtual string GetCloseButton()
{
var element = new TagBuilder("button");
element.Attributes.Add("type", "button");
element.Attributes.Add("data-dismiss", "modal");
element.AddCssClass("btn");
element.AddCssClass("btn-secondary");
element.InnerHtml.Append(_localizer["Close"]);
return element.ToHtmlString();
}
protected virtual string GetCancelButton()
{
var element = new TagBuilder("button");
element.Attributes.Add("type", "button");
element.Attributes.Add("data-dismiss", "modal");
element.AddCssClass("btn");
element.AddCssClass("btn-secondary");
element.InnerHtml.Append(_localizer["Cancel"]);
return element.ToHtmlString();
}
protected virtual void ProcessButtonsAlignment(TagHelperOutput output)
{
if (TagHelper.ButtonAlignment == ButtonsAlign.Default)
@ -62,6 +108,6 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal
return;
}
output.Attributes.AddClass("justify-content-" + TagHelper.ButtonAlignment.ToString().ToLowerInvariant());
}
}
}
}
}
}

38
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Modal/AbpModalHeaderTagHelperService.cs

@ -1,11 +1,20 @@
using System.Text;
using Localization.Resources.AbpUi;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.Extensions.Localization;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal
{
public class AbpModalHeaderTagHelperService : AbpTagHelperService<AbpModalHeaderTagHelper>
{
protected IStringLocalizer<AbpUiResource> L { get; }
public AbpModalHeaderTagHelperService(IStringLocalizer<AbpUiResource> localizer)
{
L = localizer;
}
public override void Process(TagHelperContext context, TagHelperOutput output)
{
output.TagName = "div";
@ -16,22 +25,27 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal
protected virtual string CreatePreContent()
{
var sb = new StringBuilder();
sb.AppendLine(" <h5 class=\"modal-title\">" + TagHelper.Title + "</h5>");
var title = new TagBuilder("h5");
title.AddCssClass("modal-title");
title.InnerHtml.Append(TagHelper.Title);
return sb.ToString();
return title.ToHtmlString();
}
protected virtual string CreatePostContent()
{
var sb = new StringBuilder();
sb.AppendLine(" <button type=\"button\" class=\"close\" data-dismiss=\"modal\" aria-label=\"Close\">");
sb.AppendLine(" <span aria-hidden=\"true\">&times;</span>");
sb.AppendLine(" </button>");
var span = new TagBuilder("span");
span.Attributes.Add("aria-hidden", "true");
span.InnerHtml.AppendHtml("&times;");
var button = new TagBuilder("button");
button.AddCssClass("close");
button.Attributes.Add("type", "button");
button.Attributes.Add("data-dismiss", "modal");
button.Attributes.Add("aria-label", L["Close"].Value);
button.InnerHtml.AppendHtml(span);
return sb.ToString();
return button.ToHtmlString();
}
}
}
}

87
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Modal/AbpModalTagHelperService.cs

@ -1,30 +1,66 @@
using System.Linq;
using System.Text;
using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Razor.TagHelpers;
using System.Text;
using System.Threading.Tasks;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal
{
public class AbpModalTagHelperService : AbpTagHelperService<AbpModalTagHelper>
{
public override void Process(TagHelperContext context, TagHelperOutput output)
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
output.TagName = null;
output.PreContent.SetHtmlContent(CreatePreContent(output));
output.PostContent.SetHtmlContent(CreatePostContent());
}
protected virtual string CreatePreContent(TagHelperOutput output)
{
var sb = new StringBuilder();
var childContent = await output.GetChildContentAsync();
SetContent(context, output, childContent);
}
var attritubutes = output.Attributes.Select(a => " " + a.Name + "=\"" + a.Value + "\" ").ToList();
var attritubutesAsJoin = string.Join(" ", attritubutes.ToArray());
protected virtual void SetContent(TagHelperContext context, TagHelperOutput output, TagHelperContent childContent)
{
var modalContent = GetModalContentElement(context, output, childContent);
var modalDialog = GetModalDialogElement(context, output, modalContent);
var modal = GetModal(context, output, modalDialog);
sb.AppendLine("<div class=\"" + GetModalClasses() + "\" tabindex=\"-1\" role=\"dialog\" aria-hidden=\"true\" " + attritubutesAsJoin + GetDataAttributes() + ">");
sb.AppendLine(" <div class=\"" + GetModalDialogClasses() + "\" role=\"document\">");
sb.AppendLine(" <div class=\"" + GetModalContentClasses() + "\">");
output.Content.SetHtmlContent(modal);
}
protected virtual TagBuilder GetModalContentElement(TagHelperContext context, TagHelperOutput output, TagHelperContent childContent)
{
var element = new TagBuilder("div");
element.AddCssClass(GetModalContentClasses());
element.InnerHtml.SetHtmlContent(childContent);
return element;
}
return sb.ToString();
protected virtual TagBuilder GetModalDialogElement(TagHelperContext context, TagHelperOutput output, IHtmlContent innerHtml)
{
var element = new TagBuilder("div");
element.AddCssClass(GetModalDialogClasses());
element.Attributes.Add("role", "document");
element.InnerHtml.SetHtmlContent(innerHtml);
return element;
}
protected virtual TagBuilder GetModal(TagHelperContext context, TagHelperOutput output, IHtmlContent innerHtml)
{
var element = new TagBuilder("div");
element.AddCssClass(GetModalClasses());
element.Attributes.Add("tabindex", "-1");
element.Attributes.Add("role", "dialog");
element.Attributes.Add("aria-hidden", "true");
foreach (var attr in output.Attributes)
{
element.Attributes.Add(attr.Name, attr.Value.ToString());
}
SetDataAttributes(element);
element.InnerHtml.SetHtmlContent(innerHtml);
return element;
}
protected virtual string GetModalClasses()
@ -63,17 +99,14 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Modal
return "data-backdrop=\"static\" ";
}
return string.Empty;
}
protected virtual string CreatePostContent()
{
var sb = new StringBuilder();
sb.AppendLine(" </div>");
sb.AppendLine(" </div>");
sb.AppendLine("</div>");
return sb.ToString();
}
protected virtual void SetDataAttributes(TagBuilder builder)
{
if (TagHelper.Static == true)
{
builder.Attributes.Add("data-backdrop", "static");
}
}
}
}

30
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Nav/AbpNavbarToggleTagHelperService.cs

@ -1,11 +1,21 @@
using System;
using Localization.Resources.AbpUi;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.Extensions.Localization;
using System;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Nav
{
public class AbpNavbarToggleTagHelperService : AbpTagHelperService<AbpNavbarToggleTagHelper>
{
protected IStringLocalizer<AbpUiResource> L { get; }
public AbpNavbarToggleTagHelperService(IStringLocalizer<AbpUiResource> stringLocalizer)
{
L = stringLocalizer;
}
public override void Process(TagHelperContext context, TagHelperOutput output)
{
SetRandomNameIfNotProvided();
@ -18,10 +28,20 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Nav
protected virtual void SetToggleButton(TagHelperContext context, TagHelperOutput output)
{
output.PreElement.SetHtmlContent(
"<button class=\"navbar-toggler\" type=\"button\" data-toggle=\"collapse\" data-target=\"#" +
TagHelper.Id + "\" aria-controls=\"" + TagHelper.Id +
"\" aria-expanded=\"false\" aria-label=\"Toggle navigation\">\r\n <span class=\"navbar-toggler-icon\"></span>\r\n </button>");
var span = new TagBuilder("span");
span.AddCssClass("navbar-toggler-icon");
var button = new TagBuilder("button");
button.AddCssClass("navbar-toggler");
button.Attributes.Add("type", "button");
button.Attributes.Add("data-toggle", "collapse");
button.Attributes.Add("data-target", "#" + TagHelper.Id);
button.Attributes.Add("aria-controls", TagHelper.Id);
button.Attributes.Add("aria-expanded", "false");
button.Attributes.Add("aria-label", L["ToggleNavigation"].Value);
button.InnerHtml.AppendHtml(span);
output.PreElement.SetHtmlContent(button);
}
protected virtual void SetRandomNameIfNotProvided()

16
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Pagination/AbpPaginationTagHelperService.cs

@ -1,13 +1,13 @@
using System;
using System.Linq;
using System.Text;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
using Localization.Resources.AbpUi;
using Localization.Resources.AbpUi;
using Microsoft.AspNetCore.Mvc.TagHelpers;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Microsoft.Extensions.Localization;
using System;
using System.Linq;
using System.Text;
using System.Text.Encodings.Web;
using System.Threading.Tasks;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions;
@ -134,7 +134,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Pagination
SetHrefAttribute(currentPage, attributeList);
tagHelperOutput.Content.SetHtmlContent(localizer[localizationKey]);
tagHelperOutput.Content.SetContent(localizer[localizationKey]);
var renderedHtml = tagHelperOutput.Render(_encoder);
@ -166,7 +166,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Pagination
var localizer = _stringLocalizerFactory.Create(typeof(AbpUiResource));
var pagerInfo = (TagHelper.ShowInfo ?? false) ?
" <div class=\"col-sm-12 col-md-5\"> " + localizer["PagerInfo{0}{1}{2}", TagHelper.Model.ShowingFrom, TagHelper.Model.ShowingTo, TagHelper.Model.TotalItemsCount] + "</div>\r\n"
" <div class=\"col-sm-12 col-md-5\"> " + _encoder.Encode(localizer["PagerInfo{0}{1}{2}", TagHelper.Model.ShowingFrom, TagHelper.Model.ShowingTo, TagHelper.Model.TotalItemsCount]) + "</div>\r\n"
: "";
return

58
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Popover/AbpPopoverTagHelperService.cs

@ -1,11 +1,20 @@
using System;
using System.Linq;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;
using System.Linq;
using System.Web;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Popover
{
public class AbpPopoverTagHelperService : AbpTagHelperService<AbpPopoverTagHelper>
{
{
protected IHtmlGenerator HtmlGenerator { get; }
public AbpPopoverTagHelperService(IHtmlGenerator htmlGenerator)
{
HtmlGenerator = htmlGenerator;
}
public override void Process(TagHelperContext context, TagHelperOutput output)
{
if (!TagHelper.Disabled ?? true)
@ -21,38 +30,51 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Popover
SetDisabled(context, output);
}
}
protected virtual void SetDisabled(TagHelperContext context, TagHelperOutput output)
{
var triggerAsHtml = TagHelper.Dismissible ?? false ? "data-trigger=\"focus\" " : "";
{
var triggerValue = TagHelper.Dismissible ?? false ? "focus" : "";
if (TagHelper.Hoverable ?? false)
{
if (triggerAsHtml.Contains("focus"))
if (triggerValue.Contains("focus"))
{
triggerAsHtml = triggerAsHtml.Replace("focus", "focus hover");
triggerValue = triggerValue.Replace("focus", "focus hover");
}
else
{
triggerAsHtml = "data-trigger=\"hover\" ";
triggerValue = "hover";
}
}
var dataPlacementAsHtml = "data-placement=\"" + GetDirectory().ToString().ToLowerInvariant() + "\" ";
}
var dataPlacement = GetDirectory().ToString().ToLowerInvariant();
// data-placement="default" with data-trigger="focus" causes Cannot read property 'indexOf' of undefined at computeAutoPlacement(bootstrap.bundle.js?_v=637146714627330435:2185) error
if (IsDismissibleOrHoverable() && GetDirectory() == PopoverDirectory.Default)
{
//dataPlacementAsHtml = string.Empty; //bootstrap default placement is right, abp's is top.
dataPlacementAsHtml = dataPlacementAsHtml.Replace("default", "top");
dataPlacement = dataPlacement.Replace("default", "top");
}
var titleAttribute = output.Attributes.FirstOrDefault(at => at.Name == "title");
var titleAsHtml = titleAttribute == null ? "" : "title=\"" + titleAttribute.Value + "\" ";
var preElementHtml = "<span tabindex=\"0\" class=\"d-inline-block\" " + titleAsHtml + triggerAsHtml + dataPlacementAsHtml + "data-toggle=\"popover\" data-content=\"" + GetDataContent() + "\">";
var postElementHtml = "</span>";
output.PreElement.SetHtmlContent(preElementHtml);
output.PostElement.SetHtmlContent(postElementHtml);
var span = new TagBuilder("span");
span.AddCssClass("d-inline-block");
span.Attributes.Add("tabindex", "0");
span.Attributes.Add("data-toggle", "popover");
span.Attributes.Add("data-content", GetDataContent());
span.Attributes.Add("data-trigger", triggerValue);
span.Attributes.Add("data-placement", dataPlacement);
if (titleAttribute != null)
{
span.Attributes.Add("title", HttpUtility.HtmlDecode(titleAttribute.Value.ToString()));
}
output.PreElement.SetHtmlContent(span.RenderStartTag());
output.PostElement.SetHtmlContent(span.RenderEndTag());
output.Attributes.Add("style", "pointer-events: none;");
}
protected virtual void SetDataTriggerIfDismissible(TagHelperContext context, TagHelperOutput output)
{
if (TagHelper.Dismissible ?? false)

35
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Tab/AbpTabDropdownTagHelperService.cs

@ -1,7 +1,8 @@
using System;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Razor.TagHelpers;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Tab
@ -31,14 +32,26 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Tab
var link = TagHelper.Name;
var title = TagHelper.Title;
return "<li class=\"nav-item dropdown\">" +
"<a class=\"nav-link dropdown-toggle\" id=\"" + id + "\" data-toggle=\"dropdown\" href=\"#" + link + "\" role=\"button\" aria-haspopup=\"true\" aria-expanded=\"false\">" +
title +
"</a>" +
"<div class=\"dropdown-menu\">" +
AbpTabDropdownItemsActivePlaceholder +
"</div>" +
"</li>";
var anchor = new TagBuilder("a");
anchor.AddCssClass("nav-link dropdown-toggle");
anchor.Attributes.Add("id", id);
anchor.Attributes.Add("data-toggle", "dropdown");
anchor.Attributes.Add("href", "#" + link);
anchor.Attributes.Add("role", "button");
anchor.Attributes.Add("aria-haspopup", "true");
anchor.Attributes.Add("aria-expanded", "false");
anchor.InnerHtml.Append(title);
var menu = new TagBuilder("div");
menu.AddCssClass("dropdown-menu");
menu.InnerHtml.Append(AbpTabDropdownItemsActivePlaceholder);
var listItem = new TagBuilder("li");
listItem.AddCssClass("nav-item dropdown");
listItem.InnerHtml.AppendHtml(anchor);
listItem.InnerHtml.AppendHtml(menu);
return listItem.ToHtmlString();
}
}
}
}

33
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Tab/AbpTabLinkTagHelperService.cs

@ -1,6 +1,7 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Razor.TagHelpers;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Tab
@ -10,7 +11,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Tab
public override Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
SetPlaceholderForNameIfNotProvided();
var tabHeader = GetTabHeaderItem(context, output);
var tabHeaderItems = context.GetValue<List<TabItem>>(TabItems);
@ -30,12 +31,28 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Tab
if (!string.IsNullOrWhiteSpace(TagHelper.ParentDropdownName))
{
return "<a class=\"dropdown-item\" id=\"" + id + "\" href=\"" + href + "\">" + title + "</a>";
var anchor = new TagBuilder("a");
anchor.AddCssClass("dropdown-item");
anchor.Attributes.Add("id", id);
anchor.Attributes.Add("href", href);
anchor.InnerHtml.Append(title);
return anchor.ToHtmlString();
}
else
{
var anchor = new TagBuilder("a");
anchor.AddCssClass("nav-link " + AbpTabItemActivePlaceholder);
anchor.Attributes.Add("id", id);
anchor.Attributes.Add("href", href);
anchor.InnerHtml.Append(title);
var listItem = new TagBuilder("li");
listItem.AddCssClass("nav-item");
listItem.InnerHtml.AppendHtml(anchor);
return "<li class=\"nav-item\"><a class=\"nav-link" + AbpTabItemActivePlaceholder + "\" id=\"" + id + "\" href=\"" + href + "\">" +
title +
"</a></li>";
return listItem.ToHtmlString();
}
}
protected virtual void SetPlaceholderForNameIfNotProvided()
@ -46,4 +63,4 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Tab
}
}
}
}
}

74
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Tab/AbpTabTagHelperService.cs

@ -1,7 +1,8 @@
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Razor.TagHelpers;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Extensions;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Tab
@ -34,16 +35,52 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Tab
var attributes = GetTabHeaderAttributes(context, output);
var classAttributesAsString = attributes.Where(a=>a.Name == "class").ToList().Select(a=>a.Value).JoinAsString(" ");
var otherAttributesAsString = attributes.Where(a => a.Name != "class").ToList().ToHtmlAttributesAsString();
var otherAttributes = attributes.Where(a => a.Name != "class").ToList();
if (!string.IsNullOrWhiteSpace(TagHelper.ParentDropdownName))
{
return "<a class=\"dropdown-item "+ classAttributesAsString + "\" id=\"" + id + "\" href=\"#" + link + "\" data-toggle=\"tab\" role=\"tab\" aria-controls=\"" + control + "\" aria-selected=\"false\" "+ otherAttributesAsString + ">" + title + "</a>";
var anchor = new TagBuilder("a");
anchor.AddCssClass("dropdown-item " + classAttributesAsString);
anchor.Attributes.Add("id", id);
anchor.Attributes.Add("href", "#" + link);
anchor.Attributes.Add("data-toggle", "tab");
anchor.Attributes.Add("role", "tab");
anchor.Attributes.Add("aria-controls", control);
anchor.Attributes.Add("aria-selected", "false");
foreach (var attr in otherAttributes)
{
anchor.Attributes.Add(attr.Name, attr.Value.ToString());
}
anchor.InnerHtml.Append(title);
return anchor.ToHtmlString();
}
else
{
var anchor = new TagBuilder("a");
anchor.AddCssClass("nav-link " + classAttributesAsString + " " + AbpTabItemActivePlaceholder);
anchor.Attributes.Add("id", id);
anchor.Attributes.Add("data-toggle", TabItemsDataTogglePlaceHolder);
anchor.Attributes.Add("href", "#" + link);
anchor.Attributes.Add("role", "tab");
anchor.Attributes.Add("aria-controls", control);
anchor.Attributes.Add("aria-selected", AbpTabItemSelectedPlaceholder);
foreach (var attr in otherAttributes)
{
anchor.Attributes.Add(attr.Name, attr.Value.ToString());
}
anchor.InnerHtml.Append(title);
var listItem = new TagBuilder("li");
listItem.AddCssClass("nav-item");
listItem.InnerHtml.AppendHtml(anchor);
return listItem.ToHtmlString();
}
return "<li class=\"nav-item\"><a class=\"nav-link " + classAttributesAsString + " " + AbpTabItemActivePlaceholder + "\" id=\"" + id + "\" data-toggle=\"" + TabItemsDataTogglePlaceHolder + "\" href=\"#" + link + "\" role=\"tab\" aria-controls=\"" + control + "\" aria-selected=\"" + AbpTabItemSelectedPlaceholder + "\" "+ otherAttributesAsString + ">" +
title +
"</a></li>";
}
protected virtual string GetTabContentItem(TagHelperContext context, TagHelperOutput output, string content)
@ -53,11 +90,22 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Tab
var attributes = GetTabContentAttributes(context, output);
var classAttributesAsString = attributes.Where(a => a.Name == "class").ToList().Select(a => a.Name).JoinAsString(" ");
var otherAttributesAsString = attributes.Where(a => a.Name != "class").ToList().ToHtmlAttributesAsString();
var otherAttributes = attributes.Where(a => a.Name != "class").ToList();
var wrapper = new TagBuilder("div");
wrapper.AddCssClass("tab-pane fade " + classAttributesAsString + " " + AbpTabItemShowActivePlaceholder);
wrapper.Attributes.Add("id", id);
wrapper.Attributes.Add("role", "tabpanel");
wrapper.Attributes.Add("aria-labelledby", headerId);
foreach (var attr in otherAttributes)
{
wrapper.Attributes.Add(attr.Name, attr.Value.ToString());
}
wrapper.InnerHtml.AppendHtml(content);
return "<div class=\"tab-pane fade " + classAttributesAsString + " " + AbpTabItemShowActivePlaceholder + "\" id=\"" + id + "\" role=\"tabpanel\" aria-labelledby=\"" + headerId + "\" " + otherAttributesAsString + ">" +
content +
"</div>";
return wrapper.ToHtmlString();
}
protected virtual void SetPlaceholderForNameIfNotProvided()
@ -83,4 +131,4 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Tab
.Select(a=> new TagHelperAttribute(a.Name.Substring(prefix.Length), a.Value)).ToList();
}
}
}
}

46
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Tab/AbpTabsTagHelperService.cs

@ -1,9 +1,11 @@
using System;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Razor.TagHelpers;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.TagHelpers;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Microsoft.AspNetCore.Razor.TagHelpers;
using Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Grid;
@ -11,6 +13,13 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Tab
{
public class AbpTabsTagHelperService : AbpTagHelperService<AbpTabsTagHelper>
{
protected IHtmlGenerator HtmlGenerator { get; }
public AbpTabsTagHelperService(IHtmlGenerator htmlGenerator)
{
HtmlGenerator = htmlGenerator;
}
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
SetRandomNameIfNotProvided();
@ -35,7 +44,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Tab
}
}
protected virtual string CombineHeadersAndContents(TagHelperContext context, TagHelperOutput output, string headers, string contents)
{
var combined = new StringBuilder();
@ -61,31 +70,34 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Tab
var navClass = TagHelper.TabStyle == TabStyle.Tab ? " nav-tabs" : " nav-pills";
var verticalClass = GetVerticalPillClassIfVertical();
var surroundedHeaders = "<ul class=\"nav" + verticalClass + navClass + "\" id=\"" + id + "\" role=\"tablist\">" + Environment.NewLine +
headers +
"</ul>";
var listElement = new TagBuilder("ul");
listElement.AddCssClass("nav" + verticalClass + navClass);
listElement.Attributes.Add("id", id);
listElement.Attributes.Add("role", "tablist");
listElement.InnerHtml.AppendHtml(headers);
return surroundedHeaders;
return listElement.ToHtmlString();
}
protected virtual string SurroundContents(TagHelperContext context, TagHelperOutput output, string contents)
{
var id = TagHelper.Name + "Content";
var surroundedContents = "<div class=\"tab-content\" id=\"" + id + "\">" + Environment.NewLine +
contents +
" </div>";
var wrapper = new TagBuilder("div");
wrapper.AddCssClass("tab-content");
wrapper.Attributes.Add("id", id);
wrapper.InnerHtml.AppendHtml(contents);
return surroundedContents;
return wrapper.ToHtmlString();
}
protected virtual string PlaceInsideColumn(string contents, int columnSize)
{
var surroundedContents = "<div class=\"col-md-" + columnSize + "\">" + Environment.NewLine +
contents +
" </div>";
var wrapper = new TagBuilder("div");
wrapper.AddCssClass("col-md-" + columnSize);
wrapper.InnerHtml.AppendHtml(contents);
return surroundedContents;
return wrapper.ToHtmlString();
}
protected virtual void PlaceInsideRow(TagHelperOutput output)
@ -213,7 +225,7 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Tab
protected virtual string SetTabItemNameIfNotProvided(string content, int index)
{
return content.Replace(TabItemNamePlaceHolder, TagHelper.Name + "_" + index);
return content.Replace(TabItemNamePlaceHolder, HtmlGenerator.Encode(TagHelper.Name) + "_" + index);
}
}
}
}

23
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/TagBuilderExtensions.cs

@ -0,0 +1,23 @@
using System.IO;
using System.Text.Encodings.Web;
using Microsoft.AspNetCore.Mvc.Rendering;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers
{
internal static class TagBuilderExtensions
{
public static string ToHtmlString(this TagBuilder tagBuilder)
{
return tagBuilder.ToHtmlString(HtmlEncoder.Default);
}
public static string ToHtmlString(this TagBuilder tagBuilder, HtmlEncoder htmlEncoder)
{
using (var writer = new StringWriter())
{
tagBuilder.WriteTo(writer, htmlEncoder);
return writer.ToString();
}
}
}
}

18
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Tooltip/AbpTooltipTagHelperService.cs

@ -1,6 +1,6 @@
using System;
using System.Linq;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Razor.TagHelpers;
using System.Linq;
namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Tooltip
{
@ -24,12 +24,16 @@ namespace Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.TagHelpers.Tooltip
var directory = GetDirectory() != TooltipDirectory.Default ? GetDirectory() : TooltipDirectory.Top;
output.Attributes.Add("data-placement", directory.ToString().ToLowerInvariant());
output.PreElement.SetHtmlContent(
"<span class=\"d-inline-block\" tabindex=\"0\" data-toggle=\"tooltip\" " +
"data-placement=\"" + directory.ToString().ToLowerInvariant() +
"\" title=\"" + GetTitle() + "\">" + Environment.NewLine);
var span = new TagBuilder("span");
span.AddCssClass("d-inline-block");
span.Attributes.Add("tabindex", "0");
span.Attributes.Add("data-toggle", "tooltip");
span.Attributes.Add("data-placement", directory.ToString().ToLowerInvariant());
span.Attributes.Add("title", GetTitle());
output.PreElement.SetHtmlContent(span.RenderStartTag());
output.PostElement.SetHtmlContent(Environment.NewLine + "</span>");
output.PostElement.SetHtmlContent(span.RenderEndTag());
output.Attributes.Add("style", "pointer-events: none;");
}

12
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/datatables/datatables-extensions.js

@ -27,6 +27,10 @@
}
};
var htmlEncode = function (html) {
return $('<div/>').text(html).html();
}
var _createDropdownItem = function (record, fieldItem, tableInstance) {
var $li = $('<li/>');
var $a = $('<a/>');
@ -41,7 +45,7 @@
$a.append($("<i>").addClass(fieldItem.iconClass + " mr-1"));
}
$a.append(fieldItem.text);
$a.append(htmlEncode(fieldItem.text));
}
if (fieldItem.action) {
@ -84,7 +88,7 @@
} else if (firstItem.iconClass) {
$button.append($("<i>").addClass(firstItem.iconClass + " mr-1"));
}
$button.append(firstItem.text);
$button.append(htmlEncode(firstItem.text));
}
if (firstItem.enabled && !firstItem.enabled({ record: record, table: tableInstance })) {
@ -128,9 +132,9 @@
}
if (field.text) {
$dropdownButton.append(field.text);
$dropdownButton.append(htmlEncode(fieldItem.text));
} else {
$dropdownButton.append(localize("DatatableActionDropdownDefaultText"));
$dropdownButton.append(htmlEncode(localize("DatatableActionDropdownDefaultText")));
}
$dropdownButton

7
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared/wwwroot/libs/abp/aspnetcore-mvc-ui-theme-shared/jquery/jquery-extensions.js

@ -35,7 +35,12 @@
//change text
if ($buttonInnerSpan.length && $button.attr('data-busy-text')) {
$button.data('buttonOriginalText', $buttonInnerSpan.html());
$buttonInnerSpan.html($button.attr('data-busy-text'));
if ($button.data('busy-text-is-html')) {
$buttonInnerSpan.html($button.attr('data-busy-text'));
} else {
$buttonInnerSpan.text($button.attr('data-busy-text'));
}
}
$button.addClass('button-busy');

3
framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Buttons.cshtml

@ -295,6 +295,9 @@
<li>
<b>busy-text</b>: Sets "data-busy-text" attribute. Default value is localization of "ProcessingWithThreeDot" string.
</li>
<li>
<b>busy-text-is-html</b>: Sets "data-busy-is-html" attribute. Default value is "false".
</li>
</ul>
</div>
</div>

32
framework/test/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo/Pages/Components/Carousel.cshtml

@ -2,6 +2,11 @@
@model Volo.Abp.AspNetCore.Mvc.UI.Bootstrap.Demo.Pages.Components.CarouselsModel
@{
ViewData["Title"] = "Carousels";
var firstSlide = "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iODAwIiBoZWlnaHQ9IjQwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgODAwIDQwMCIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+PGRlZnM+PHN0eWxlIHR5cGU9InRleHQvY3NzIj4jaG9sZGVyXzE2MzQzY2ZiNzEyIHRleHQgeyBmaWxsOiM0NDQ7Zm9udC13ZWlnaHQ6bm9ybWFsO2ZvbnQtZmFtaWx5OkhlbHZldGljYSwgbW9ub3NwYWNlO2ZvbnQtc2l6ZTo0MHB0IH0gPC9zdHlsZT48L2RlZnM+PGcgaWQ9ImhvbGRlcl8xNjM0M2NmYjcxMiI+PHJlY3Qgd2lkdGg9IjgwMCIgaGVpZ2h0PSI0MDAiIGZpbGw9IiM2NjYiPjwvcmVjdD48Zz48dGV4dCB4PSIyNDcuMjkxNjcxNzUyOTI5NyIgeT0iMjE4LjMiPkZpcnN0IHNsaWRlPC90ZXh0PjwvZz48L2c+PC9zdmc+";
var secondSlide = "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iODAwIiBoZWlnaHQ9IjQwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgODAwIDQwMCIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+PGRlZnM+PHN0eWxlIHR5cGU9InRleHQvY3NzIj4jaG9sZGVyXzE2MzQzY2ZiNzEyIHRleHQgeyBmaWxsOiM0NDQ7Zm9udC13ZWlnaHQ6bm9ybWFsO2ZvbnQtZmFtaWx5OkhlbHZldGljYSwgbW9ub3NwYWNlO2ZvbnQtc2l6ZTo0MHB0IH0gPC9zdHlsZT48L2RlZnM+PGcgaWQ9ImhvbGRlcl8xNjM0M2NmYjcxMiI+PHJlY3Qgd2lkdGg9IjgwMCIgaGVpZ2h0PSI0MDAiIGZpbGw9IiM2NjYiPjwvcmVjdD48Zz48dGV4dCB4PSIyNDcuMjkxNjcxNzUyOTI5NyIgeT0iMjE4LjMiPlNlY29uZCBzbGlkZTwvdGV4dD48L2c+PC9nPjwvc3ZnPg==";
var thirdSlide = "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iODAwIiBoZWlnaHQ9IjQwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgODAwIDQwMCIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+PGRlZnM+PHN0eWxlIHR5cGU9InRleHQvY3NzIj4jaG9sZGVyXzE2MzQzY2ZiNzE0IHRleHQgeyBmaWxsOiMzMzM7Zm9udC13ZWlnaHQ6bm9ybWFsO2ZvbnQtZmFtaWx5OkhlbHZldGljYSwgbW9ub3NwYWNlO2ZvbnQtc2l6ZTo0MHB0IH0gPC9zdHlsZT48L2RlZnM+PGcgaWQ9ImhvbGRlcl8xNjM0M2NmYjcxNCI+PHJlY3Qgd2lkdGg9IjgwMCIgaGVpZ2h0PSI0MDAiIGZpbGw9IiM1NTUiPjwvcmVjdD48Zz48dGV4dCB4PSIyNzYuOTc0OTk4NDc0MTIxMSIgeT0iMjE4LjMiPlRoaXJkIHNsaWRlPC90ZXh0PjwvZz48L2c+PC9zdmc+";
}
@section styles {
@ -31,11 +36,10 @@
<div class="demo-with-code">
<div class="demo-area">
<abp-carousel indicators="false" controls="false">
<abp-carousel-item src="data:image/svg+xml;charset=UTF-8,%3Csvg width%3D&quot;800&quot; height%3D&quot;400&quot; xmlns%3D&quot;http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg&quot; viewBox%3D&quot;0 0 800 400&quot; preserveAspectRatio%3D&quot;none&quot;%3E%3Cdefs%3E%3Cstyle type%3D&quot;text%2Fcss&quot;%3E%23holder_16343cfb712 text %7B fill%3A%23444%3Bfont-weight%3Anormal%3Bfont-family%3AHelvetica%2C monospace%3Bfont-size%3A40pt %7D %3C%2Fstyle%3E%3C%2Fdefs%3E%3Cg id%3D&quot;holder_16343cfb712&quot;%3E%3Crect width%3D&quot;800&quot; height%3D&quot;400&quot; fill%3D&quot;%23666&quot;%3E%3C%2Frect%3E%3Cg%3E%3Ctext x%3D&quot;247.2916717529297&quot; y%3D&quot;218.3&quot;%3EFirst slide%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E"></abp-carousel-item>
<abp-carousel-item src="data:image/svg+xml;charset=UTF-8,%3Csvg width%3D&quot;800&quot; height%3D&quot;400&quot; xmlns%3D&quot;http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg&quot; viewBox%3D&quot;0 0 800 400&quot; preserveAspectRatio%3D&quot;none&quot;%3E%3Cdefs%3E%3Cstyle type%3D&quot;text%2Fcss&quot;%3E%23holder_16343cfb712 text %7B fill%3A%23444%3Bfont-weight%3Anormal%3Bfont-family%3AHelvetica%2C monospace%3Bfont-size%3A40pt %7D %3C%2Fstyle%3E%3C%2Fdefs%3E%3Cg id%3D&quot;holder_16343cfb712&quot;%3E%3Crect width%3D&quot;800&quot; height%3D&quot;400&quot; fill%3D&quot;%23666&quot;%3E%3C%2Frect%3E%3Cg%3E%3Ctext x%3D&quot;247.2916717529297&quot; y%3D&quot;218.3&quot;%3ESecond slide%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E"></abp-carousel-item>
<abp-carousel-item src="data:image/svg+xml;charset=UTF-8,%3Csvg width%3D&quot;800&quot; height%3D&quot;400&quot; xmlns%3D&quot;http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg&quot; viewBox%3D&quot;0 0 800 400&quot; preserveAspectRatio%3D&quot;none&quot;%3E%3Cdefs%3E%3Cstyle type%3D&quot;text%2Fcss&quot;%3E%23holder_16343cfb714 text %7B fill%3A%23333%3Bfont-weight%3Anormal%3Bfont-family%3AHelvetica%2C monospace%3Bfont-size%3A40pt %7D %3C%2Fstyle%3E%3C%2Fdefs%3E%3Cg id%3D&quot;holder_16343cfb714&quot;%3E%3Crect width%3D&quot;800&quot; height%3D&quot;400&quot; fill%3D&quot;%23555&quot;%3E%3C%2Frect%3E%3Cg%3E%3Ctext x%3D&quot;276.9749984741211&quot; y%3D&quot;218.3&quot;%3EThird slide%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E"></abp-carousel-item>
<abp-carousel-item src="@firstSlide"></abp-carousel-item>
<abp-carousel-item src="@secondSlide"></abp-carousel-item>
<abp-carousel-item src="@thirdSlide"></abp-carousel-item>
</abp-carousel>
</div>
<div class="code-area">
@ -76,9 +80,9 @@
<div class="demo-area">
<abp-carousel indicators="false">
<abp-carousel-item src="data:image/svg+xml;charset=UTF-8,%3Csvg width%3D&quot;800&quot; height%3D&quot;400&quot; xmlns%3D&quot;http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg&quot; viewBox%3D&quot;0 0 800 400&quot; preserveAspectRatio%3D&quot;none&quot;%3E%3Cdefs%3E%3Cstyle type%3D&quot;text%2Fcss&quot;%3E%23holder_16343cfb712 text %7B fill%3A%23444%3Bfont-weight%3Anormal%3Bfont-family%3AHelvetica%2C monospace%3Bfont-size%3A40pt %7D %3C%2Fstyle%3E%3C%2Fdefs%3E%3Cg id%3D&quot;holder_16343cfb712&quot;%3E%3Crect width%3D&quot;800&quot; height%3D&quot;400&quot; fill%3D&quot;%23666&quot;%3E%3C%2Frect%3E%3Cg%3E%3Ctext x%3D&quot;247.2916717529297&quot; y%3D&quot;218.3&quot;%3EFirst slide%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E"></abp-carousel-item>
<abp-carousel-item src="data:image/svg+xml;charset=UTF-8,%3Csvg width%3D&quot;800&quot; height%3D&quot;400&quot; xmlns%3D&quot;http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg&quot; viewBox%3D&quot;0 0 800 400&quot; preserveAspectRatio%3D&quot;none&quot;%3E%3Cdefs%3E%3Cstyle type%3D&quot;text%2Fcss&quot;%3E%23holder_16343cfb712 text %7B fill%3A%23444%3Bfont-weight%3Anormal%3Bfont-family%3AHelvetica%2C monospace%3Bfont-size%3A40pt %7D %3C%2Fstyle%3E%3C%2Fdefs%3E%3Cg id%3D&quot;holder_16343cfb712&quot;%3E%3Crect width%3D&quot;800&quot; height%3D&quot;400&quot; fill%3D&quot;%23666&quot;%3E%3C%2Frect%3E%3Cg%3E%3Ctext x%3D&quot;247.2916717529297&quot; y%3D&quot;218.3&quot;%3ESecond slide%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E"></abp-carousel-item>
<abp-carousel-item src="data:image/svg+xml;charset=UTF-8,%3Csvg width%3D&quot;800&quot; height%3D&quot;400&quot; xmlns%3D&quot;http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg&quot; viewBox%3D&quot;0 0 800 400&quot; preserveAspectRatio%3D&quot;none&quot;%3E%3Cdefs%3E%3Cstyle type%3D&quot;text%2Fcss&quot;%3E%23holder_16343cfb714 text %7B fill%3A%23333%3Bfont-weight%3Anormal%3Bfont-family%3AHelvetica%2C monospace%3Bfont-size%3A40pt %7D %3C%2Fstyle%3E%3C%2Fdefs%3E%3Cg id%3D&quot;holder_16343cfb714&quot;%3E%3Crect width%3D&quot;800&quot; height%3D&quot;400&quot; fill%3D&quot;%23555&quot;%3E%3C%2Frect%3E%3Cg%3E%3Ctext x%3D&quot;276.9749984741211&quot; y%3D&quot;218.3&quot;%3EThird slide%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E"></abp-carousel-item>
<abp-carousel-item src="@firstSlide"></abp-carousel-item>
<abp-carousel-item src="@secondSlide"></abp-carousel-item>
<abp-carousel-item src="@thirdSlide"></abp-carousel-item>
</abp-carousel>
</div>
<div class="code-area">
@ -127,9 +131,9 @@
<div class="demo-area">
<abp-carousel>
<abp-carousel-item src="data:image/svg+xml;charset=UTF-8,%3Csvg width%3D&quot;800&quot; height%3D&quot;400&quot; xmlns%3D&quot;http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg&quot; viewBox%3D&quot;0 0 800 400&quot; preserveAspectRatio%3D&quot;none&quot;%3E%3Cdefs%3E%3Cstyle type%3D&quot;text%2Fcss&quot;%3E%23holder_16343cfb712 text %7B fill%3A%23444%3Bfont-weight%3Anormal%3Bfont-family%3AHelvetica%2C monospace%3Bfont-size%3A40pt %7D %3C%2Fstyle%3E%3C%2Fdefs%3E%3Cg id%3D&quot;holder_16343cfb712&quot;%3E%3Crect width%3D&quot;800&quot; height%3D&quot;400&quot; fill%3D&quot;%23666&quot;%3E%3C%2Frect%3E%3Cg%3E%3Ctext x%3D&quot;247.2916717529297&quot; y%3D&quot;218.3&quot;%3EFirst slide%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E"></abp-carousel-item>
<abp-carousel-item src="data:image/svg+xml;charset=UTF-8,%3Csvg width%3D&quot;800&quot; height%3D&quot;400&quot; xmlns%3D&quot;http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg&quot; viewBox%3D&quot;0 0 800 400&quot; preserveAspectRatio%3D&quot;none&quot;%3E%3Cdefs%3E%3Cstyle type%3D&quot;text%2Fcss&quot;%3E%23holder_16343cfb712 text %7B fill%3A%23444%3Bfont-weight%3Anormal%3Bfont-family%3AHelvetica%2C monospace%3Bfont-size%3A40pt %7D %3C%2Fstyle%3E%3C%2Fdefs%3E%3Cg id%3D&quot;holder_16343cfb712&quot;%3E%3Crect width%3D&quot;800&quot; height%3D&quot;400&quot; fill%3D&quot;%23666&quot;%3E%3C%2Frect%3E%3Cg%3E%3Ctext x%3D&quot;247.2916717529297&quot; y%3D&quot;218.3&quot;%3ESecond slide%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E"></abp-carousel-item>
<abp-carousel-item src="data:image/svg+xml;charset=UTF-8,%3Csvg width%3D&quot;800&quot; height%3D&quot;400&quot; xmlns%3D&quot;http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg&quot; viewBox%3D&quot;0 0 800 400&quot; preserveAspectRatio%3D&quot;none&quot;%3E%3Cdefs%3E%3Cstyle type%3D&quot;text%2Fcss&quot;%3E%23holder_16343cfb714 text %7B fill%3A%23333%3Bfont-weight%3Anormal%3Bfont-family%3AHelvetica%2C monospace%3Bfont-size%3A40pt %7D %3C%2Fstyle%3E%3C%2Fdefs%3E%3Cg id%3D&quot;holder_16343cfb714&quot;%3E%3Crect width%3D&quot;800&quot; height%3D&quot;400&quot; fill%3D&quot;%23555&quot;%3E%3C%2Frect%3E%3Cg%3E%3Ctext x%3D&quot;276.9749984741211&quot; y%3D&quot;218.3&quot;%3EThird slide%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E"></abp-carousel-item>
<abp-carousel-item src="@firstSlide"></abp-carousel-item>
<abp-carousel-item src="@secondSlide"></abp-carousel-item>
<abp-carousel-item src="@thirdSlide"></abp-carousel-item>
</abp-carousel>
</div>
<div class="code-area">
@ -183,7 +187,7 @@
<div class="demo-area">
<abp-carousel>
<abp-carousel-item caption-title="Second slide label" caption="Lorem ipsum dolor sit amet, consectetur adipiscing elit." src="data:image/svg+xml;charset=UTF-8,%3Csvg width%3D&quot;800&quot; height%3D&quot;400&quot; xmlns%3D&quot;http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg&quot; viewBox%3D&quot;0 0 800 400&quot; preserveAspectRatio%3D&quot;none&quot;%3E%3Cdefs%3E%3Cstyle type%3D&quot;text%2Fcss&quot;%3E%23holder_16343cfb712 text %7B fill%3A%23444%3Bfont-weight%3Anormal%3Bfont-family%3AHelvetica%2C monospace%3Bfont-size%3A40pt %7D %3C%2Fstyle%3E%3C%2Fdefs%3E%3Cg id%3D&quot;holder_16343cfb712&quot;%3E%3Crect width%3D&quot;800&quot; height%3D&quot;400&quot; fill%3D&quot;%23666&quot;%3E%3C%2Frect%3E%3Cg%3E%3Ctext x%3D&quot;247.2916717529297&quot; y%3D&quot;218.3&quot;%3EFirst slide%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E"></abp-carousel-item>
<abp-carousel-item caption-title="Second slide label" caption="Lorem ipsum dolor sit amet, consectetur adipiscing elit." src="@firstSlide"></abp-carousel-item>
</abp-carousel>
</div>
<div class="code-area">
@ -234,9 +238,9 @@
<div class="demo-area">
<abp-carousel indicators="false" crossfade="true">
<abp-carousel-item src="data:image/svg+xml;charset=UTF-8,%3Csvg width%3D&quot;800&quot; height%3D&quot;400&quot; xmlns%3D&quot;http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg&quot; viewBox%3D&quot;0 0 800 400&quot; preserveAspectRatio%3D&quot;none&quot;%3E%3Cdefs%3E%3Cstyle type%3D&quot;text%2Fcss&quot;%3E%23holder_16343cfb712 text %7B fill%3A%23444%3Bfont-weight%3Anormal%3Bfont-family%3AHelvetica%2C monospace%3Bfont-size%3A40pt %7D %3C%2Fstyle%3E%3C%2Fdefs%3E%3Cg id%3D&quot;holder_16343cfb712&quot;%3E%3Crect width%3D&quot;800&quot; height%3D&quot;400&quot; fill%3D&quot;%23666&quot;%3E%3C%2Frect%3E%3Cg%3E%3Ctext x%3D&quot;247.2916717529297&quot; y%3D&quot;218.3&quot;%3EFirst slide%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E"></abp-carousel-item>
<abp-carousel-item src="data:image/svg+xml;charset=UTF-8,%3Csvg width%3D&quot;800&quot; height%3D&quot;400&quot; xmlns%3D&quot;http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg&quot; viewBox%3D&quot;0 0 800 400&quot; preserveAspectRatio%3D&quot;none&quot;%3E%3Cdefs%3E%3Cstyle type%3D&quot;text%2Fcss&quot;%3E%23holder_16343cfb712 text %7B fill%3A%23444%3Bfont-weight%3Anormal%3Bfont-family%3AHelvetica%2C monospace%3Bfont-size%3A40pt %7D %3C%2Fstyle%3E%3C%2Fdefs%3E%3Cg id%3D&quot;holder_16343cfb712&quot;%3E%3Crect width%3D&quot;800&quot; height%3D&quot;400&quot; fill%3D&quot;%23666&quot;%3E%3C%2Frect%3E%3Cg%3E%3Ctext x%3D&quot;247.2916717529297&quot; y%3D&quot;218.3&quot;%3ESecond slide%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E"></abp-carousel-item>
<abp-carousel-item src="data:image/svg+xml;charset=UTF-8,%3Csvg width%3D&quot;800&quot; height%3D&quot;400&quot; xmlns%3D&quot;http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg&quot; viewBox%3D&quot;0 0 800 400&quot; preserveAspectRatio%3D&quot;none&quot;%3E%3Cdefs%3E%3Cstyle type%3D&quot;text%2Fcss&quot;%3E%23holder_16343cfb714 text %7B fill%3A%23333%3Bfont-weight%3Anormal%3Bfont-family%3AHelvetica%2C monospace%3Bfont-size%3A40pt %7D %3C%2Fstyle%3E%3C%2Fdefs%3E%3Cg id%3D&quot;holder_16343cfb714&quot;%3E%3Crect width%3D&quot;800&quot; height%3D&quot;400&quot; fill%3D&quot;%23555&quot;%3E%3C%2Frect%3E%3Cg%3E%3Ctext x%3D&quot;276.9749984741211&quot; y%3D&quot;218.3&quot;%3EThird slide%3C%2Ftext%3E%3C%2Fg%3E%3C%2Fg%3E%3C%2Fsvg%3E"></abp-carousel-item>
<abp-carousel-item src="@firstSlide"></abp-carousel-item>
<abp-carousel-item src="@secondSlide"></abp-carousel-item>
<abp-carousel-item src="@thirdSlide"></abp-carousel-item>
</abp-carousel>
</div>
<div class="code-area">

Loading…
Cancel
Save