Skip to content

Create AbpText and AbpDynamicText#25469

Open
blackWins wants to merge 2 commits into
abpframework:devfrom
blackWins:mvc-ui
Open

Create AbpText and AbpDynamicText#25469
blackWins wants to merge 2 commits into
abpframework:devfrom
blackWins:mvc-ui

Conversation

@blackWins

@blackWins blackWins commented May 23, 2026

Copy link
Copy Markdown
Contributor

New AbpTextTagHelper

New AbpDynamicTextTagHelper

How to test it?

image

abp-text

Usage:

<abp-text asp-for="@Model.Name"/>
<abp-text asp-for="@Model.Description "/>
public class FormElementsModel : PageModel
{
        [Display(Name = "User Name")]
        public string Name { get; set; }

        [AbpText(LabelWidth = ColumnSize._3, Format = "<i class=\"fa-solid fa-book\"></i> <strong>{0}</strong>")]
        public string Description { get; set; }
}

Tag Attributes

  • label-width : Sets the width of the label column. Default is ColumnSize._4 .
  • suppress-label : When true , hides the label.
  • format : Sets a format string for the value.

abp-dynamic-text

Usage:

<abp-dynamic-text abp-model="@Model.MyModel" column-size="_6"/>
public class FormElementsModel : PageModel
{
    public SampleModel MyModel { get; set; }

    public void OnGet()
    {
        MyModel = new SampleModel();
    }

    public class SampleModel
    {
        public string Name { get; set; }

        [AbpText(Format = "yyyy-MM-dd")]
        public DateTime BirthDate { get; set; }
        
        public StatusType Status { get; set; }
        
        public Address Address { get; set; }
    }
    
    public class Address
    {
        public string City { get; set; }
        
        public string Street { get; set; }
    }
    
    public enum StatusType
    {
        Active,
        Inactive
    }
}

Tag Attributes

  • abp-model : Sets the c# model for dynamic form. Properties of this modal are turned into inputs in the form.
  • column-size : Use ColumnSize enum.
  • label-width : Sets the width of the label column. Default is ColumnSize._4 .

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds new Bootstrap UI form tag helpers to render read-only “text” fields (single field and model-driven dynamic rendering) in ABP’s ASP.NET Core MVC UI layer.

Changes:

  • Introduces abp-text to render a label/value row for a single asp-for model expression.
  • Introduces abp-dynamic-text to render multiple abp-text blocks by traversing a provided model (abp-model).
  • Adds an [AbpText] attribute intended to control formatting/label behavior from model metadata.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpTextTagHelperService.cs Implements HTML generation and type-specific rendering for abp-text.
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpTextTagHelper.cs Defines the abp-text tag helper attributes (asp-for, label-width, format, etc.).
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpText.cs Adds [AbpText] attribute for property-level configuration.
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpDynamicTextTagHelperService.cs Implements model traversal and rendering multiple abp-text instances.
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpDynamicTextTagHelper.cs Defines the abp-dynamic-text tag helper (abp-model, column-size, label-width).

Comment on lines +171 to +180
var modelType = value.GetType();
var enumType = modelType.IsEnum ? modelType : Nullable.GetUnderlyingType(modelType);
var containerLocalizer = _tagHelperLocalizer.GetLocalizerOrNull(TagHelper.AspFor.ModelExplorer.Container.ModelType.Assembly);
var localizedMemberName = value == null ? "-" : _abpEnumLocalizer.GetString(enumType!, (int)value,
new[]
{
containerLocalizer,
_stringLocalizerFactory.CreateDefaultOrNull()
}!);
return HtmlEncoder.Encode(localizedMemberName ?? string.Empty);
Comment on lines +86 to +92
if (!TagHelper.SuppressLabel)
{
var labelWidth = $"col-{(int)TagHelper.LabelWidth}";
contentBuilder.AppendLine($"<div class=\"{labelWidth}\">");
contentBuilder.AppendLine(labelHtml);
contentBuilder.AppendLine("</div>");
}
Comment on lines +186 to +201

var format = TagHelper.Format ?? TagHelper.AspFor.ModelExplorer.GetAttribute<AbpText>()?.Format;

if (value is DateTime dateTime)
{
return dateTime.ToString(format);
}

if (value is DateTimeOffset dateTimeOffset)
{
return dateTimeOffset.ToString(format);
}

return value.ToString() ?? string.Empty;
}


protected virtual string GetFileValue()
{
return "<span class=\"text-info\"><i class=\"bi bi-file\"></i> File</span>";
Comment on lines +221 to +235
protected virtual string GetCollectionValue()
{
var value = TagHelper.AspFor.Model;

//todo Consider supporting collection render.
if (value is System.Collections.IEnumerable enumerable)
{
var count = 0;
foreach (var item in enumerable)
{
count++;
}

return count.ToString();
}
@@ -0,0 +1,278 @@
using System;
using System.Collections.Generic;
using System.Reflection.Emit;
@@ -0,0 +1,21 @@
using System;
using Microsoft.AspNetCore.Razor.TagHelpers;
Comment on lines +23 to +39
protected HtmlEncoder HtmlEncoder { get; }
protected IServiceProvider ServiceProvider { get; }
protected List<ModelExpression> Models = new();
protected readonly IAbpEnumLocalizer AbpEnumLocalizer;
protected readonly IStringLocalizerFactory StringLocalizerFactory;

public AbpDynamicTextTagHelperService(
HtmlEncoder htmlEncoder,
IServiceProvider serviceProvider,
IAbpEnumLocalizer abpEnumLocalizer,
IStringLocalizerFactory stringLocalizerFactory
)
{
HtmlEncoder = htmlEncoder;
ServiceProvider = serviceProvider;
AbpEnumLocalizer = abpEnumLocalizer;
StringLocalizerFactory = stringLocalizerFactory;
Comment on lines +36 to +45
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
var childContent = await output.GetChildContentAsync();

NormalizeTagMode(context, output);
SetAttributes(context, output);

var html = GetHtml(context, output);
SetContent(context, output, html, childContent);
}
@hikalkan hikalkan requested review from hikalkan and removed request for hikalkan June 15, 2026 13:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants