Browse Source

Merge branch 'dev' into salihozkara/seo

pull/16136/head
Salih 4 years ago
parent
commit
f681331ad4
  1. 114
      docs/en/Blog-Posts/2023-03-24-status.abp.io/POST.md
  2. BIN
      docs/en/Blog-Posts/2023-03-24-status.abp.io/images/discord.png
  3. BIN
      docs/en/Blog-Posts/2023-03-24-status.abp.io/images/gh-status.png
  4. BIN
      docs/en/Blog-Posts/2023-03-24-status.abp.io/images/issue.png
  5. BIN
      docs/en/Blog-Posts/2023-03-24-status.abp.io/images/status-abpio.png
  6. 16
      docs/en/Community-Articles/2023-03-27-What-is-new-in-NET8/post.md
  7. 12
      docs/en/UI/Blazor/Toolbars.md
  8. 131
      docs/zh-Hans/UI/Angular/Multi-Tenancy.md
  9. 266
      docs/zh-Hans/UI/AspNetCore/Tag-Helpers/Form-elements.md
  10. 2
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelper.cs
  11. 1
      framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelperService.cs
  12. 2
      framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepository.cs
  13. 3
      npm/ng-packs/packages/core/src/lib/core.module.ts
  14. 1
      npm/ng-packs/packages/core/src/lib/pipes/index.ts
  15. 13
      npm/ng-packs/packages/core/src/lib/pipes/safe-html.pipe.ts
  16. 12
      npm/ng-packs/packages/theme-basic/src/lib/components/page-alert-container/page-alert-container.component.html

114
docs/en/Blog-Posts/2023-03-24-status.abp.io/POST.md

@ -0,0 +1,114 @@
# Creating a Custom Status Page for abp.io with Upptime
## Introduction
In today's digital world, providing reliable and transparent information about your platform's availability is essential to maintaining trust among your community and customers. With the growing number of abp.io users, we needed a dedicated status page [status.abp.io](https://status.abp.io/) to keep everyone informed about our platform's health. To achieve this, we utilized the open-source project [Upptime](https://upptime.js.org/) and built a custom status page on [GitHub Pages](https://pages.github.com/). In this article, we'll guide you through the process of creating our own status page and customizing it to suit our needs.
![status-abpio](./images/status-abpio.png)
## Why we chose Upptime
[Upptime](https://github.com/upptime/upptime) is an open-source, easy-to-use, and cost-effective solution for monitoring websites and APIs. It offers essential features, such as downtime alerts, response time monitoring, and status history. We decided to use Upptime because of its compatibility with GitHub Pages, ease of customization, comprehensive [documentation ](https://upptime.js.org/docs/) and discord notifications.
![gh-status](./images/gh-status.png)
#### Advantages of Upptime
* Open-source: Allows easy customization and community support.
* GitHub Pages compatibility: Seamless integration with GitHub Pages for hosting.
* Cost-effective: Utilizes GitHub Actions, which provides free monitoring within the GitHub Actions usage limits.
* Comprehensive documentation: Easy-to-follow instructions for setting up and customizing the status page.
#### Disadvantages of Upptime
* Limited monitoring capabilities: Upptime offers basic monitoring features but lacks advanced capabilities found in dedicated monitoring tools.
* Dependence on GitHub Actions: Upptime relies on GitHub Actions, which may pose limitations for users unfamiliar with GitHub's ecosystem or those with large-scale projects.
* No built-in alerting system: Users must rely on third-party integrations or custom solutions for notifications, requiring additional configuration.
* Limited customization options: Upptime allows for some customization, but options are limited compared to comprehensive monitoring platforms.
* Self-hosted limitations: As a self-hosted solution, users are responsible for maintaining and managing their own infrastructure, which may not be ideal for those who prefer a fully managed monitoring solution.
## How to set up the status page on GitHub Pages
To get started with our custom status page, we followed the instructions in the [Upptime documentation](https://upptime.js.org/docs/). Here's a summary of the steps we took:
* Fork the Upptime [template repository](https://github.com/upptime/upptime) to our own GitHub account as [abpio-status](https://github.com/abpframework/abpio-status).
* Configure the GitHub Actions workflow. We configured the GitHub Actions workflow by adding the following lines to the [`.github/workflows/uptime.yml`](https://github.com/abpframework/abpio-status/blob/master/.github/workflows/uptime.yml)
* Add the monitored endpoints. We added the monitored endpoints (our abp.io websites) to the [.upptimerc.yml](https://github.com/abpframework/abpio-status/blob/master/.upptimerc.yml) file. This file is located in the root of the repository and contains a list of URLs that Upptime monitors.
```yaml
sites:
- name: abp.io
url: https://abp.io/health-status
- name: community.abp.io
url: https://community.abp.io/health-status
- name: commercial.abp.io
url: https://commercial.abp.io/health-status
- name: nuget.abp.io
url: https://nuget.abp.io/health-status
- name: docs.abp.io
url: https://docs.abp.io/health-status
- name: support.abp.io
url: https://support.abp.io/health-status
- name: blog.abp.io
url: https://blog.abp.io/health-status
- name: commercial-demo.abp.io
url: https://commercial-demo.abp.io/health-status
```
* Enable GitHub Pages. Finally, we enabled GitHub Pages for our forked repository by going to the repository's settings and selecting the gh-pages branch as the source. This made our status page accessible at [status.abp.io](https://status.abp.io/).
## Customizing the status page
After setting up the default Upptime status page, we focused on customizing it to align with our brand and provide a consistent experience for our community and customers. We made the following changes:
* Updating the logo and favicon. We replaced the default logo and favicon with our own abp.io branded assets. This involved adding the new image files to the repository and updating the references in the `.upptimerc.yml` file:
* Customizing the color scheme and typography. We customized the color scheme and typography to match our corporate identity by editing the `.upptimerc.yml` file:
```yaml
status-website:
theme: dark
# Add your custom domain name, or remove the `cname` line if you don't have a domain
# Uncomment the `baseUrl` line if you don't have a custom domain and add your repo name there
cname: status.abp.io
# baseUrl: /abpio-status
logoUrl: https://commercial.abp.io/assets/svg/abp-logo-light.svg
favicon: https://raw.githubusercontent.com/abpframework/abpio-status/master/assets/abp-logo-without-text.svg
faviconSvg: https://raw.githubusercontent.com/abpframework/abpio-status/master/assets/abp-logo-without-text.svg
```
## Creating GitHub Issues for Maintenance Information on status.abp.io
To provide maintenance information for your status page, you can create GitHub issues in your repository. This allows you to inform your users about planned downtime or ongoing maintenance work.
![issue](./images/issue.png)
## Discord Notifications
### Create a Discord Webhook
To set up Discord notifications for your status.abp.io status page using [Upptime documentation](https://upptime.js.org/docs/notifications#discord), follow these steps:
* In Discord, go to "Server Settings" > "Integrations" > "Create Webhook."
* Customize the Webhook name, choose a channel, and copy the Webhook URL.
### Configure GitHub Actions
* In your Upptime repository, go to the "Settings" tab.
* Click on "Secrets" and then "New repository secret."
* Add secret: Name it DISCORD_WEBHOOK_URL and paste the Webhook URL as the value.
* Add environment variables NOTIFICATION_DISCORD_WEBHOOK and NOTIFICATION_DISCORD set it to true.
Your status page will now send notifications to your Discord channel whenever there's a change in your platform's status.
![discord](./images/discord.png)
## Conclusion
If your primary goal is to create a simple, cost-effective status page with basic monitoring features, Upptime is an excellent choice. Its open-source nature, seamless integration with GitHub Pages, and comprehensive documentation make it a user-friendly option.
If you require advanced monitoring capabilities or prefer a fully managed monitoring solution, you may want to explore dedicated monitoring tools, such as Pingdom, Uptime Robot, or Datadog. These tools typically offer more robust monitoring features, built-in alerting systems, and customizable dashboards.
Creating a custom status page for abp.io using Upptime and GitHub Pages proved to be an efficient and cost-effective solution. By following the documentation and customizing the template, we were able to provide our community and customers with a reliable source of information about our platform's availability. With this new status page [status.abp.io](https://status.abp.io/), we can continue to build trust and transparency as our platform grows and evolves.

BIN
docs/en/Blog-Posts/2023-03-24-status.abp.io/images/discord.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 KiB

BIN
docs/en/Blog-Posts/2023-03-24-status.abp.io/images/gh-status.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 394 KiB

BIN
docs/en/Blog-Posts/2023-03-24-status.abp.io/images/issue.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

BIN
docs/en/Blog-Posts/2023-03-24-status.abp.io/images/status-abpio.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 KiB

16
docs/en/Community-Articles/2023-03-27-What-is-new-in-NET8/post.md

@ -15,7 +15,7 @@ dotnet publish -p:PublishRelease=false -> /app/bin/Debug/net8.0/app.dll
## `System.Text.Json` Serialization 🧱 ## System.Text.Json Serialization 🧱
[System.Text.Json](https://learn.microsoft.com/en-us/dotnet/api/system.text.json) replaced Newtonsoft.Json in the recent versions. We are also using `System.Text.Json` in the [ABP Framework](https://abp.io) now. There are several enhancements to object serialization and deserialization. [System.Text.Json](https://learn.microsoft.com/en-us/dotnet/api/system.text.json) replaced Newtonsoft.Json in the recent versions. We are also using `System.Text.Json` in the [ABP Framework](https://abp.io) now. There are several enhancements to object serialization and deserialization.
@ -25,7 +25,9 @@ The latest version of the [source generator](https://learn.microsoft.com/en-us/d
## Randomness ## Randomness
AI programming is very popular these days. And the need to produce more random content arose.
### GetItems<T>() 🧮 ### GetItems<T>() 🧮
@ -60,7 +62,7 @@ Finland -> 358
### Shuffle<T>() 🔀 ### Shuffle<T>() 🔀
If you need to randomize the order of a span in your program, you can take advantage of two new methods: [Random.Shuffle](https://learn.microsoft.com/en-us/dotnet/api/system.random.shuffle) and [RandomNumberGenerator.Shuffle](https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.randomnumbergenerator.shuffle#system-security-cryptography-randomnumbergenerator-shuffle-1(system-span((-0)). These methods are particularly handy when you want to minimize the impact of training bias in machine learning by varying the order in which training and testing data are presented. Using these methods, you can ensure that the first thing in your dataset is only sometimes used for training, and the last is only sometimes reserved for testing. If you need to randomize the order of a span in your application, you can take advantage of two new methods: [Random.Shuffle](https://learn.microsoft.com/en-us/dotnet/api/system.random.shuffle) and [RandomNumberGenerator.Shuffle](https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.randomnumbergenerator.shuffle?view=net-8.0). These methods are particularly handy when you want to minimize the impact of training bias in machine learning by varying the order in which training and testing data are presented. Using these methods, you can ensure that the first thing in your dataset is only sometimes used for training, and the last is only sometimes reserved for testing.
```csharp ```csharp
var trainingData = GetData(); var trainingData = GetData();
@ -110,7 +112,7 @@ In .NET 8, various new types have been introduced to enhance application perform
## Improvements in `System.Numerics` and `System.Runtime.Intrinsics` 🔥 ## Improvements in System.Numerics and System.Runtime.Intrinsics 🔥
There are several enhancements made to the [System.Numerics](https://learn.microsoft.com/en-us/dotnet/api/system.numerics) and [System.Runtime.Intrinsics](https://learn.microsoft.com/en-us/dotnet/api/system.runtime.intrinsics) namespaces. These improvements include better hardware acceleration for [Vector256](https://learn.microsoft.com/en-us/dotnet/api/system.runtime.intrinsics.vector256-1), [Matrix3x2](https://learn.microsoft.com/en-us/dotnet/api/system.numerics.matrix3x2), and [Matrix4x4](https://learn.microsoft.com/en-us/dotnet/api/system.numerics.matrix4x4) in .NET 8. There are several enhancements made to the [System.Numerics](https://learn.microsoft.com/en-us/dotnet/api/system.numerics) and [System.Runtime.Intrinsics](https://learn.microsoft.com/en-us/dotnet/api/system.runtime.intrinsics) namespaces. These improvements include better hardware acceleration for [Vector256](https://learn.microsoft.com/en-us/dotnet/api/system.runtime.intrinsics.vector256-1), [Matrix3x2](https://learn.microsoft.com/en-us/dotnet/api/system.numerics.matrix3x2), and [Matrix4x4](https://learn.microsoft.com/en-us/dotnet/api/system.numerics.matrix4x4) in .NET 8.
@ -183,7 +185,7 @@ In .NET 8, the support for native AOT now encompasses the `x64` and `Arm64` arch
## .NET 8 Devops Improvements 📦 ## .NET 8 DevOps Improvements 📦
### NET Container Image Changes ### NET Container Image Changes
@ -210,7 +212,9 @@ The support requirements for Linux have been updated for .NET 8, with changes to
For further details, please refer to the [support for Red Hat Enterprise Linux Family](https://github.com/dotnet/core/blob/main/linux-support.md#red-hat-enterprise-linux-family-support) page. For further details, please refer to the [support for Red Hat Enterprise Linux Family](https://github.com/dotnet/core/blob/main/linux-support.md#red-hat-enterprise-linux-family-support) page.
〰️〰️〰️
---
Become a pioneer and try the new features of .NET 8 now. Become a pioneer and try the new features of .NET 8 now.
Adapt it to your project or start a new .NET 8 project. Adapt it to your project or start a new .NET 8 project.

12
docs/en/UI/Blazor/Toolbars.md

@ -40,6 +40,10 @@ This sample simply shows a message. In real life, you probably want to call an H
Now, we can create a class implementing the `IToolbarContributor` interface: Now, we can create a class implementing the `IToolbarContributor` interface:
````csharp ````csharp
using Volo.Abp.AspNetCore.Components.Web.Theming.Toolbars;
// ...
public class MyToolbarContributor : IToolbarContributor public class MyToolbarContributor : IToolbarContributor
{ {
public Task ConfigureToolbarAsync(IToolbarConfigurationContext context) public Task ConfigureToolbarAsync(IToolbarConfigurationContext context)
@ -58,12 +62,16 @@ This class adds the `NotificationViewComponent` as the first item in the `Main`
Finally, you need to add this contributor to the `AbpToolbarOptions`, in the `ConfigureServices` of your [module](../../Module-Development-Basics.md): Finally, you need to add this contributor to the `AbpToolbarOptions`, in the `ConfigureServices` of your [module](../../Module-Development-Basics.md):
````csharp ```csharp
using Volo.Abp.AspNetCore.Components.Web.Theming.Toolbars;
```
```csharp
Configure<AbpToolbarOptions>(options => Configure<AbpToolbarOptions>(options =>
{ {
options.Contributors.Add(new MyToolbarContributor()); options.Contributors.Add(new MyToolbarContributor());
}); });
```` ```
That's all, you will see the notification icon on the toolbar when you run the application: That's all, you will see the notification icon on the toolbar when you run the application:

131
docs/zh-Hans/UI/Angular/Multi-Tenancy.md

@ -1 +1,130 @@
TODO... # 在 Angular UI 中的多租户支持
ABP Angular UI 支持多租户,以下是与多租户相关的一些特性:
![Tenants Page](./images/tenants-page.png)
<p style="font-size:small;text-align:center;">租户页面</p>
在上面的页面中,您可以:
- 查看所有租户。
- 创建新的租户。
- 编辑现有租户。
- 删除租户。
![Tenant Switching Component](./images/tenant-switching-box.png)
<p style="font-size:small;text-align:center;">租户切换组件</p>
您可以在 MVC Account Public Module 的子页面(如登录页面)中使用租户切换框来在现有租户之间切换。Angular UI 从 `application-configuration` 响应中获取选定的租户,并在每个请求中将租户 ID 作为 `__tenant` header 发送到后端。
## 域名/子域名租户解析器
> **注意:** 如果要执行下面的步骤,您还应该实现后端的域名/子域名租户解析器功能。请参阅[多租户文档中的域名/子域名租户解析器](../../Multi-Tenancy#domain-subdomain-tenant-resolver)以了解后端实现。
Angular UI 可以从运行 URL 中获取租户名称。您可以通过子域名(如 mytenant1.mydomain.com)或整个域名(如 mytenant.com)来确定当前租户。要做到这一点,您需要在环境中设置 `application.baseUrl` 属性:
子域名解析器:
```js
// environment.prod.ts
export const environment = {
//...
application: {
baseUrl: "https://{0}.mydomain.com/",
},
//...
};
```
**{0}** 是用于确定当前租户唯一名称的占位符。
在上述配置完成后,如果您的应用程序运行在 `mytenant1.mydomain.com` 上,应用程序将获取租户名称为 **mytenant1**。接下来,应用程序将调用 `/api/abp/multi-tenancy/tenants/by-name/mytenant1` 端点来检查租户是否存在。如果租户(mytenant1)存在,则应用程序将保留此租户数据,并在每个请求中将其 `id` 作为 `__tenant` header 发送到后端。如果租户不存在,则应用程序不会将 `__tenant` header 发送到后端。
> **重要提示:** 如果在 `baseUrl` 中使用了占位符(**{0}**),则子页面(如登录页面)中 `AccountLayoutComponent` 中的租户切换组件将被隐藏。
域名解析器:
```js
// environment.prod.ts
export const environment = {
//...
application: {
baseUrl: "https://{0}.com/",
},
//...
};
```
配置完成后,如果您的应用程序运行在 `mytenant.com` 上,应用程序将获取租户名称为 **mytenant**。
### 租户特定的入口
在环境中,可以将占位符 **{0}** 放入 API URL 中以确定租户特定的入口。
```js
// environment.prod.ts
export const environment = {
//...
application: {
baseUrl: "https://{0}.mydomain.com/",
//...
},
oAuthConfig: {
issuer: "https://{0}.ids.mydomain.com",
//...
},
apis: {
default: {
url: "https://{0}.api.mydomain.com",
},
AbpIdentity: {
url: "https://{0}.identity.mydomain.com",
},
},
};
```
> **重要提示:** `application.baseUrl`和`baseUrl`属性中的 `{0}` 占位符是必需的,以便从运行 URL 中获取租户。API URL 中的其他占位符是可选的。
在上述配置完成后,如果您的应用程序运行在 `mytenant1.mydomain.com`上,应用程序将获取租户名称为 **mytenant1** ,并在应用程序初始化时将环境对象替换为 `EnvironmentService` 中的以下内容:
```js
// environment object in EnvironmentService
{
//...
application: {
baseUrl: 'https://mytenant1.mydomain.com/',
//...
},
oAuthConfig: {
issuer: 'https://mytenant1.ids.mydomain.com',
//...
},
apis: {
default: {
url: 'https://mytenant1.api.mydomain.com',
},
AbpIdentity: {
url: 'https://mytenant1.identity.mydomain.com',
},
},
}
```
替换后,应用程序将使用以下 URL:
- `https://mytenant1.ids.mydomain.com` 作为 AuthServer URL。
- `https://mytenant1.api.mydomain.com` 作为默认 URL。
- `https://mytenant1.identity.mydomain.com` 作为 `AbpIdentity` 入点口 URL.
应用程序在每个请求中发送包含当前租户 id 的 `__tenant` header.
## 参见
- [ABP 中的多租户](../../Multi-Tenancy.md)

266
docs/zh-Hans/UI/AspNetCore/Tag-Helpers/Form-elements.md

@ -1 +1,265 @@
TODO...
# 表单元素
## 简介
Abp提供表单输入标签助手以便更轻松地构建表单。
## 演示
请查看[表单元素演示页面](https://bootstrap-taghelpers.abp.io/Components/FormElements)。
## abp-input
`abp-input`标签为给定的C#属性创建一个Bootstrap表单输入。它在后台使用了[Asp.Net Core Input Tag Helper](https://docs.microsoft.com/tr-tr/aspnet/core/mvc/views/working-with-forms?view=aspnetcore-3.1#the-input-tag-helper),所以Asp.Net Core的每个input标签助手的数据注释属性对于`abp-input`也有效。
用法:
````xml
<abp-input asp-for="@Model.MyModel.Name"/>
<abp-input asp-for="@Model.MyModel.Description"/>
<abp-input asp-for="@Model.MyModel.Password"/>
<abp-input asp-for="@Model.MyModel.IsActive"/>
````
Model:
````csharp
public class FormElementsModel : PageModel
{
public SampleModel MyModel { get; set; }
public void OnGet()
{
MyModel = new SampleModel();
}
public class SampleModel
{
[Required]
[Placeholder("Enter your name...")]
[InputInfoText("What is your name?")]
public string Name { get; set; }
[Required]
[FormControlSize(AbpFormControlSize.Large)]
public string SurName { get; set; }
[TextArea(Rows = 4)]
public string Description { get; set; }
[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
public bool IsActive { get; set; }
}
}
````
### 特性(Attributes)
你可以在你的c#属性上设置一些特性,或者直接在html标签上设置。如果您要在[abp-dynamic-form](Dynamic-forms.md)中使用此属性,则只能通过属性特性设置这些属性。
#### 属性特性(Property Attributes)
- `[TextArea()]`: 将输入转换为文本区域。
* `[Placeholder()]`: 为输入设置占位符。您可以直接使用本地化键。
* `[InputInfoText()]`: 为输入设置小型信息文本。您可以直接使用本地化键。
* `[FormControlSize()]`: 设置表单控件包装器元素的大小。可用的值为
- `AbpFormControlSize.Default`
- `AbpFormControlSize.Small`
- `AbpFormControlSize.Medium`
- `AbpFormControlSize.Large`
* `[DisabledInput]` : 输入被禁用。
* `[ReadOnlyInput]`: 输入为只读。
#### 标签属性(Tag Attributes)
* `info`: 为输入设置小型信息文本。您可以直接使用本地化键。
* `auto-focus`: 如果为true,则浏览器会自动聚焦在该元素上。
* `size`: 设置表单控件包装器元素的大小。可用的值为
- `AbpFormControlSize.Default`
- `AbpFormControlSize.Small`
- `AbpFormControlSize.Medium`
- `AbpFormControlSize.Large`
* `disabled`: 输入被禁用。
* `readonly`: 输入为只读。
* `label`: 为输入设置标签。
* `display-required-symbol`: 如果输入为必填项,则向标签添加必需符号(*)。默认为`True`。
[Asp.Net Core Input Tag Helper](https://docs.microsoft.com/en-us/aspnet/core/mvc/views/working-with-forms?view=aspnetcore-3.1#the-input-tag-helper)的`asp-format`、`name`和`value`属性也对`abp-input`标签助手有效。
### 标签和本地化
您可以通过不同的方式设置输入的标签:
- 您可以使用`Label`属性直接设置标签。 但是,它不会自动本地化您的本地化键。 因此,请使用`label = "@L [“ {LocalizationKey}”] .Value"`。
- 您可以使用Asp.Net Core的`[Display(name = "{LocalizationKey}")]`属性设置标签。
- 您可以让 **abp** 查找属性的本地化键。 如果未设置`label`或`[DisplayName]`属性,则会尝试查找“DisplayName:{PropertyName}”或“{PropertyName}”本地化键。
## abp-select
`abp-select` 标签为给定的 C# 属性创建了一个 Bootstrap 表单选择器。它在后台使用 [Asp.Net Core 选择标签助手](https://docs.microsoft.com/tr-tr/aspnet/core/mvc/views/working-with-forms?view=aspnetcore-3.1#the-select-tag-helper),因此 `Asp.Net Core` 的 `select` 标签助手的每个数据注释属性也适用于 `abp-select`。
`abp-select` 标签需要一个 `Microsoft.AspNetCore.Mvc.Rendering.SelectListItem` 的列表来工作。它可以通过标签上的 `asp-items` 属性或 C# 属性上的 `[SelectItems()]` 属性来提供(如果您使用的是 [abp-dynamic-form](Dynamic-forms.md),则只能使用 C# 属性的方式。)
`abp-select` 支持多重选择。
`abp-select` 自动为 **枚举(Enum)** 属性创建选择列表。不需要额外的数据。如果属性是可空的,则会在自动生成的列表顶部添加一个空键和值。
使用:
````xml
<abp-select asp-for="@Model.MyModel.City" asp-items="@Model.CityList"/>
<abp-select asp-for="@Model.MyModel.AnotherCity"/>
<abp-select asp-for="@Model.MyModel.MultipleCities" asp-items="@Model.CityList"/>
<abp-select asp-for="@Model.MyModel.MyCarType"/>
<abp-select asp-for="@Model.MyModel.MyNullableCarType"/>
````
Model:
````csharp
public class FormElementsModel : PageModel
{
public SampleModel MyModel { get; set; }
public List<SelectListItem> CityList { get; set; }
public void OnGet()
{
MyModel = new SampleModel();
CityList = new List<SelectListItem>
{
new SelectListItem { Value = "NY", Text = "New York"},
new SelectListItem { Value = "LDN", Text = "London"},
new SelectListItem { Value = "IST", Text = "Istanbul"},
new SelectListItem { Value = "MOS", Text = "Moscow"}
};
}
public class SampleModel
{
public string City { get; set; }
[SelectItems(nameof(CityList))]
public string AnotherCity { get; set; }
public List<string> MultipleCities { get; set; }
public CarType MyCarType { get; set; }
public CarType? MyNullableCarType { get; set; }
}
public enum CarType
{
Sedan,
Hatchback,
StationWagon,
Coupe
}
}
````
### 属性
您可以在 C# 属性上或直接在 HTML 标签上设置一些属性。如果您将在 [abp-dynamic-form](Dynamic-forms.md) 中使用此属性,则只能通过属性属性设置这些属性。
#### 属性特性(Property Attributes)
* `[SelectItems()]`: 设置选择数据。参数应为数据列表的名称。(见上面的示例)
- `[InputInfoText()]`:设置输入的小信息文本。您可以直接使用本地化键。
- `[FormControlSize()]`:设置表单控件包装元素的大小。可用值为
- `AbpFormControlSize.Default`
- `AbpFormControlSize.Small`
- `AbpFormControlSize.Medium`
- `AbpFormControlSize.Large`
#### 标签属性(Tag Attributes)
- `asp-items`: 设置选择数据。这应该是一个 `SelectListItem` 列表。
- `info`: 为输入设置一个小的信息文本。您可以直接使用本地化键。
- `size`: 设置表单控件包装元素的大小。可用值为
- `AbpFormControlSize.Default`
- `AbpFormControlSize.Small`
- `AbpFormControlSize.Medium`
- `AbpFormControlSize.Large`
- `label`: 为输入设置标签。
- `display-required-symbol`: 如果输入是必需的,则向标签添加必需符号 (*)。默认为 `True`。
### 标签和本地化
您可以以不同的方式设置输入的标签:
- 您可以使用 `Label` 属性并直接设置标签。但是它不会自动本地化您的本地化键。因此,请将其用作 `label="@L["{LocalizationKey}"].Value"`。
- 您可以使用 Asp.Net Core 的 `[Display(name="{LocalizationKey}")]` 属性进行设置。
- 您可以让 **abp** 查找属性的本地化键。它将尝试查找“DisplayName:{PropertyName}”或“{PropertyName}”本地化键。
对于**枚举**属性,`abp-select`会设置下拉框的本地化值。它会查找"{EnumTypeName}.{EnumPropertyName}"或"{EnumPropertyName}"的本地化键。例如,在上面的示例中,当它本地化下拉框的值时,它将使用"CarType.StationWagon"或"StationWagon"键。
## abp-radio
`abp-radio`标签为给定的C#属性创建一个Bootstrap表单单选框组。使用方式与`abp-select`标签非常相似。
Usage:
````xml
<abp-radio asp-for="@Model.MyModel.CityRadio" asp-items="@Model.CityList" inline="true"/>
<abp-radio asp-for="@Model.MyModel.CityRadio2"/>
````
Model:
````csharp
public class FormElementsModel : PageModel
{
public SampleModel MyModel { get; set; }
public List<SelectListItem> CityList { get; set; } = new List<SelectListItem>
{
new SelectListItem { Value = "NY", Text = "New York"},
new SelectListItem { Value = "LDN", Text = "London"},
new SelectListItem { Value = "IST", Text = "Istanbul"},
new SelectListItem { Value = "MOS", Text = "Moscow"}
};
public void OnGet()
{
MyModel = new SampleModel();
MyModel.CityRadio = "IST";
MyModel.CityRadio2 = "MOS";
}
public class SampleModel
{
public string CityRadio { get; set; }
[SelectItems(nameof(CityList))]
public string CityRadio2 { get; set; }
}
}
````
### 特性(attributes)
您可以在C#属性或直接在HTML标签上设置一些属性。如果您将在[abp-dynamic-form](Dynamic-forms.md)中使用此属性,则只能通过属性属性设置这些属性。
#### 属性特性(Property Attributes)
- `[SelectItems()]`:设置选择数据。参数应为数据列表的名称。 (见上面的示例)
#### 标签特性(Tag Attributes)
- `asp-items`: 设置选择数据。这应该是一个SelectListItem列表。
- `Inline`: 如果为true,则单选按钮将在单行中,相互紧挨着。如果为false,则它们将在彼此下面。

2
framework/src/Volo.Abp.AspNetCore.Mvc.UI.Bootstrap/TagHelpers/Form/AbpSelectTagHelper.cs

@ -37,6 +37,8 @@ public class AbpSelectTagHelper : AbpTagHelper<AbpSelectTagHelper, AbpSelectTagH
public string AutocompleteSelectedItemName { get; set; } public string AutocompleteSelectedItemName { get; set; }
public string AutocompleteSelectedItemValue { get; set; } public string AutocompleteSelectedItemValue { get; set; }
public string AutocompleteParentSelector { get; set; }
public string AllowClear { get; set; } public string AllowClear { get; set; }

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

@ -125,6 +125,7 @@ public class AbpSelectTagHelperService : AbpTagHelperService<AbpSelectTagHelper>
output.Attributes.Add("data-autocomplete-selected-item-value", TagHelper.AutocompleteSelectedItemValue); output.Attributes.Add("data-autocomplete-selected-item-value", TagHelper.AutocompleteSelectedItemValue);
output.Attributes.Add("data-autocomplete-allow-clear", TagHelper.AllowClear); output.Attributes.Add("data-autocomplete-allow-clear", TagHelper.AllowClear);
output.Attributes.Add("data-autocomplete-placeholder", TagHelper.Placeholder); output.Attributes.Add("data-autocomplete-placeholder", TagHelper.Placeholder);
output.Attributes.Add("data-autocomplete-parent-selector", TagHelper.AutocompleteParentSelector);
} }
} }

2
framework/src/Volo.Abp.MongoDB/Volo/Abp/Domain/Repositories/MongoDB/MongoDbRepository.cs

@ -610,7 +610,7 @@ public class MongoDbRepository<TMongoDbContext, TEntity>
return Task.CompletedTask; return Task.CompletedTask;
} }
private void TriggerEntityCreateEvents(TEntity entity) protected virtual void TriggerEntityCreateEvents(TEntity entity)
{ {
EntityChangeEventHelper.PublishEntityCreatedEvent(entity); EntityChangeEventHelper.PublishEntityCreatedEvent(entity);
} }

3
npm/ng-packs/packages/core/src/lib/core.module.ts

@ -33,6 +33,7 @@ import { getInitialData, localeInitializer } from './utils/initial-utils';
import { ShortDateTimePipe } from './pipes/short-date-time.pipe'; import { ShortDateTimePipe } from './pipes/short-date-time.pipe';
import { ShortTimePipe } from './pipes/short-time.pipe'; import { ShortTimePipe } from './pipes/short-time.pipe';
import { ShortDatePipe } from './pipes/short-date.pipe'; import { ShortDatePipe } from './pipes/short-date.pipe';
import { SafeHtmlPipe } from './pipes/safe-html.pipe';
import { QUEUE_MANAGER } from './tokens/queue.token'; import { QUEUE_MANAGER } from './tokens/queue.token';
import { DefaultQueueManager } from './utils/queue'; import { DefaultQueueManager } from './utils/queue';
import { IncludeLocalizationResourcesProvider } from './providers/include-localization-resources.provider'; import { IncludeLocalizationResourcesProvider } from './providers/include-localization-resources.provider';
@ -63,6 +64,7 @@ import { IncludeLocalizationResourcesProvider } from './providers/include-locali
ReplaceableTemplateDirective, ReplaceableTemplateDirective,
RouterOutletComponent, RouterOutletComponent,
SortPipe, SortPipe,
SafeHtmlPipe,
StopPropagationDirective, StopPropagationDirective,
ToInjectorPipe, ToInjectorPipe,
ShortDateTimePipe, ShortDateTimePipe,
@ -90,6 +92,7 @@ import { IncludeLocalizationResourcesProvider } from './providers/include-locali
ReplaceableTemplateDirective, ReplaceableTemplateDirective,
RouterOutletComponent, RouterOutletComponent,
SortPipe, SortPipe,
SafeHtmlPipe,
StopPropagationDirective, StopPropagationDirective,
ToInjectorPipe, ToInjectorPipe,
ShortDateTimePipe, ShortDateTimePipe,

1
npm/ng-packs/packages/core/src/lib/pipes/index.ts

@ -1,4 +1,5 @@
export * from './localization.pipe'; export * from './localization.pipe';
export * from './safe-html.pipe';
export * from './sort.pipe'; export * from './sort.pipe';
export * from './to-injector.pipe'; export * from './to-injector.pipe';
export * from './short-date.pipe'; export * from './short-date.pipe';

13
npm/ng-packs/packages/core/src/lib/pipes/safe-html.pipe.ts

@ -0,0 +1,13 @@
import { inject, Injectable, Pipe, PipeTransform, SecurityContext } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';
@Injectable()
@Pipe({ name: 'abpSafeHtml' })
export class SafeHtmlPipe implements PipeTransform {
private readonly sanitizer = inject(DomSanitizer);
transform(value: string): string {
if (typeof value !== 'string') return '';
return this.sanitizer.sanitize(SecurityContext.HTML, value);
}
}

12
npm/ng-packs/packages/theme-basic/src/lib/components/page-alert-container/page-alert-container.component.html

@ -4,10 +4,14 @@
[ngClass]="{ 'alert-dismissible fade show': alert.dismissible }" [ngClass]="{ 'alert-dismissible fade show': alert.dismissible }"
role="alert" role="alert"
> >
<h4 class="alert-heading" *ngIf="alert.title"> <h4
{{ alert.title | abpLocalization: alert.titleLocalizationParams }} class="alert-heading"
</h4> *ngIf="alert.title"
{{ alert.message | abpLocalization: alert.messageLocalizationParams }} [innerHTML]="alert.title | abpSafeHtml | abpLocalization: alert.titleLocalizationParams"
></h4>
<span
[innerHTML]="alert.message | abpSafeHtml | abpLocalization: alert.messageLocalizationParams"
></span>
<button <button
*ngIf="alert.dismissible" *ngIf="alert.dismissible"
type="button" type="button"

Loading…
Cancel
Save