mirror of
https://gitee.com/ant-design-blazor/ant-design-blazor.git
synced 2024-12-14 08:51:27 +08:00
chore: merge master into feature (#1323)
* fix(module: table): ExpandableRow not working with ActionColumn #1284 (#1285) * (fix) Table ExpandableRow not working with ActionColumn #1284 * Add Tree Button Expand on Action Columm. Check the position of Selection Column when calculate the position for expand button on tree mode and expand mode. * fix(module: rate): Value has priority over DefaultValue (#1303) * chore: add GitHub Actions for auto preview (#1205) * chore: add github actions for auto preview * fix setup job * chore: add GitHub Actions for auto preview (#1205) * fix(module:rate): prevent reset to default value Co-authored-by: James Yeung <shunjiey@hotmail.com> * feat(module: form): Add LabelTemplate for FormItem (#1293) Co-authored-by: Leishi <lluo@octet.com> * fix(module: table): fix DataIndex Column with incorrect sorting and filter (#1295) * refactor(module: table): Unify the behavior of Field and DataIndex * fix(module: table): Fix DataIndex Column doesn't refresh * doc(module: table): add DataIndex column filter demo * doc(module: table): fix Blazor table Co-authored-by: James Yeung <shunjiey@hotmail.com> * fix(module: datepicker): DatePicker DisabledDate works incorect (#1298) * fix(module: datepicker): DatePicker DisabledDate works incorect * test(module: dateHelperTests): modify test case Co-authored-by: James Yeung <shunjiey@hotmail.com> * fix(module: upload): Upload list update fix (#1301) * chore: add GitHub Actions for auto preview (#1205) * chore: add github actions for auto preview * fix setup job * chore: add GitHub Actions for auto preview (#1205) * fix(module:upload): file list update * fix(module:upload): typed args for file upload * fix(module:upload): delete button remove from picture-card Co-authored-by: James Yeung <shunjiey@hotmail.com> * fix(module: textarea): default to empty string (#1305) * chore: add GitHub Actions for auto preview (#1205) * chore: add github actions for auto preview * fix setup job * chore: add GitHub Actions for auto preview (#1205) * fix(module:textarea): add parameter DefaultToEmptyString * fix(module:textarea): occasional crashes of js in firefox * docs(module:input): added new param DefaultToEmptyString Co-authored-by: James Yeung <shunjiey@hotmail.com> * fix(module: grid): missing flex and wrap style (#1296) * fix(module: grid): missing flex style * remove the old md file * fix demos * fix build error * fix no warp class * docs: add changelog in document (#1306) * fix(module: select): load icon for multiple mode & value reload on delay (#1307) * chore: add GitHub Actions for auto preview (#1205) * chore: add github actions for auto preview * fix setup job * chore: add GitHub Actions for auto preview (#1205) * fix(module:select): add loading for multiple mode * fix(module:select): selected items duplication for multiple mode when values changed outside the component Co-authored-by: James Yeung <shunjiey@hotmail.com> * fix(module: table): perf optimization & data source change issue (#1304) * chore: add GitHub Actions for auto preview (#1205) * chore: add github actions for auto preview * fix setup job * chore: add GitHub Actions for auto preview (#1205) * fix(module:table): guard against false entries in _dataSourceCache * fix(module:table): perf - double to single render on datasource change * fix(module:table): perf optimization to avoid multiple renders Co-authored-by: James Yeung <shunjiey@hotmail.com> * fix(module: select): propagation on item remove (#1308) * fix(module: table): fix table re-render when ScrollX is set (#1311) * docs(module: table): fix RouterPagging demo (#1313) * chagnelog 0.7.4 (#1321) Co-authored-by: Magehernan <magehernan@gmail.com> Co-authored-by: Andrzej Bakun <andrzej@neelyc.com.cy> Co-authored-by: ldsenow <ldsenow@gmail.com> Co-authored-by: Leishi <lluo@octet.com> Co-authored-by: Zonciu Liang <zonciu@zonciu.com> Co-authored-by: 笨木头 <musicvs@163.com>
This commit is contained in:
commit
7c5de2302f
@ -15,16 +15,36 @@ timeline: true
|
||||
|
||||
---
|
||||
|
||||
### 0.7.4
|
||||
|
||||
`2021-04-08`
|
||||
|
||||
- Table
|
||||
- 🐞 Fixed issue with table not being re-rendered when setting ScrollX. [#1311](https://github.com/ant-design-blazor/ant-design-blazor/pull/1311) [@Zonciu](https://github.com/Zonciu)
|
||||
- 🐞 Fixed an issue where modifying a DataSource would throw an exception. [5b0dbfb](https://github.com/ant-design-blazor/ant-design-blazor/commit/5b0dbfb) [@Andrzej Bakun](https://github.com/Andrzej Bakun)
|
||||
- 🐞 Fix DataIndex Column Filter, make DataIndex column refresh correctly. [#1295](https://github.com/ant-design-blazor/ant-design-blazor/pull/1295) [@Zonciu](https://github.com/Zonciu)
|
||||
- 🐞 ExpandIconColumnIndex invalid when specified to the ActionColumn. [#1285](https://github.com/ant-design-blazor/ant-design-blazor/pull/1285) [@Magehernan](https://github.com/Magehernan)
|
||||
- Select
|
||||
- 🐞 Fixed an issue where clicking the Close option on multiple selections would trigger a drop-down menu. [#1308](https://github.com/ant-design-blazor/ant-design-blazor/pull/1308) [@anddrzejb](https://github.com/anddrzejb)
|
||||
- 🐞 Fixed Loading icon in Tag mode. [12ca2f7](https://github.com/ant-design-blazor/ant-design-blazor/commit/12ca2f7) [@Andrzej Bakun](https://github.com/Andrzej Bakun)
|
||||
- 💄 fix missing flex and wrap style. [#1296](https://github.com/ant-design-blazor/ant-design-blazor/pull/1296) [@ElderJames](https://github.com/ElderJames)
|
||||
- 🐞 default to empty string. [6944c13](https://github.com/ant-design-blazor/ant-design-blazor/commit/6944c13) [@Andrzej Bakun](https://github.com/Andrzej Bakun)
|
||||
- 🐞 Fix Upload list [53c1285](https://github.com/ant-design-blazor/ant-design-blazor/commit/53c1285) [@Andrzej Bakun](https://github.com/Andrzej Bakun)
|
||||
- 🐞 Fix DatePicker DisabledDate works incorect. [#1298](https://github.com/ant-design-blazor/ant-design-blazor/pull/1298) [@mutouzdl](https://github.com/mutouzdl)
|
||||
- 🆕 Added LabelTemplate in FormItem. [#1293](https://github.com/ant-design-blazor/ant-design-blazor/pull/1293) [@ldsenow](https://github.com/ldsenow)
|
||||
- 🐞 Value has priority over DefaultValue. [5f14377](https://github.com/ant-design-blazor/ant-design-blazor/commit/5f14377) [@Andrzej Bakun](https://github.com/Andrzej Bakun)
|
||||
- 📖 fix Table RouterPagging demo. [#1313](https://github.com/ant-design-blazor/ant-design-blazor/pull/1313) [@Zonciu](https://github.com/Zonciu)
|
||||
|
||||
## 0.7.3
|
||||
|
||||
`2021-03-29`
|
||||
|
||||
- 🐞 Fixed Dropdown: Animations for down and up are inverse. [#1274](https://github.com/ant-design/ant-design/pull/1274) [@mutouzdl](https://github.com/mutouzdl)
|
||||
- 🐞 Fixed Tree nodes expand incorrectly. [#1275](https://github.com/ant-design/ant-design/pull/1275) [@TimChen44](https://github.com/TimChen44)
|
||||
- 💄 Fixed Cascader an issue where the style attribute could not affect the style. [#1269](https://github.com/ant-design/ant-design/pull/1269) [@ElderJames](https://github.com/ElderJames)
|
||||
- 🐞 Fixed Datepicker [selected date on end picker]、[quarter panel's ranges] are incorrect. [#1260](https://github.com/ant-design/ant-design/pull/1260) [@mutouzdl](https://github.com/mutouzdl)
|
||||
- 📖 chore: add the copyright of .NET Foundation. [#1272](https://github.com/ant-design/ant-design/pull/1272) [@ElderJames](https://github.com/ElderJames)
|
||||
- 📖 chore: fix cmd for preview site and style sync. [68c7539](https://github.com/ant-design/ant-design/commit/68c7539) [@ElderJames](https://github.com/ElderJames)
|
||||
- 🐞 Fixed Dropdown: Animations for down and up are inverse. [#1274](https://github.com/ant-design-blazor/ant-design-blazor/pull/1274) [@mutouzdl](https://github.com/mutouzdl)
|
||||
- 🐞 Fixed Tree nodes expand incorrectly. [#1275](https://github.com/ant-design-blazor/ant-design-blazor/pull/1275) [@TimChen44](https://github.com/TimChen44)
|
||||
- 💄 Fixed Cascader an issue where the style attribute could not affect the style. [#1269](https://github.com/ant-design-blazor/ant-design-blazor/pull/1269) [@ElderJames](https://github.com/ElderJames)
|
||||
- 🐞 Fixed Datepicker [selected date on end picker]、[quarter panel's ranges] are incorrect. [#1260](https://github.com/ant-design-blazor/ant-design-blazor/pull/1260) [@mutouzdl](https://github.com/mutouzdl)
|
||||
- 📖 chore: add the copyright of .NET Foundation. [#1272](https://github.com/ant-design-blazor/ant-design-blazor/pull/1272) [@ElderJames](https://github.com/ElderJames)
|
||||
- 📖 chore: fix cmd for preview site and style sync. [68c7539](https://github.com/ant-design-blazor/ant-design-blazor/commit/68c7539) [@ElderJames](https://github.com/ElderJames)
|
||||
|
||||
## 0.7.2
|
||||
|
||||
|
@ -15,16 +15,36 @@ timeline: true
|
||||
|
||||
---
|
||||
|
||||
### 0.7.4
|
||||
|
||||
`2021-04-08`
|
||||
|
||||
- Table
|
||||
- 🐞 修复设置ScrollX时表格不重新渲染的问题。[#1311](https://github.com/ant-design-blazor/ant-design-blazor/pull/1311) [@Zonciu](https://github.com/Zonciu)
|
||||
- 🐞 修改修改DataSource会抛出异常的问题。[5b0dbfb](https://github.com/ant-design-blazor/ant-design-blazor/commit/5b0dbfb) [@Andrzej Bakun](https://github.com/Andrzej Bakun)
|
||||
- 🐞 修复DataIndex列过滤器无效的问题, 修复DataIndex列不刷新的问题。[#1295](https://github.com/ant-design-blazor/ant-design-blazor/pull/1295) [@Zonciu](https://github.com/Zonciu)
|
||||
- 🐞 ExpandIconColumnIndex 指定到 ActionColumn 时无效的问题。[#1285](https://github.com/ant-design-blazor/ant-design-blazor/pull/1285) [@Magehernan](https://github.com/Magehernan)
|
||||
- Select
|
||||
- 🐞 修复多选时点击关闭选项时,会触发下拉菜单的问题。[#1308](https://github.com/ant-design-blazor/ant-design-blazor/pull/1308) [@anddrzejb](https://github.com/anddrzejb)
|
||||
- 🐞 修复 Tag模式的 Loading 图标问题。[12ca2f7](https://github.com/ant-design-blazor/ant-design-blazor/commit/12ca2f7) [@Andrzej Bakun](https://github.com/Andrzej Bakun)
|
||||
- 💄 修复 flex 和 wrap 的样式。[#1296](https://github.com/ant-design-blazor/ant-design-blazor/pull/1296) [@ElderJames](https://github.com/ElderJames)
|
||||
- 🐞 使默认值为空字符串。[6944c13](https://github.com/ant-design-blazor/ant-design-blazor/commit/6944c13) [@Andrzej Bakun](https://github.com/Andrzej Bakun)
|
||||
- 🐞 修复文件列表。[53c1285](https://github.com/ant-design-blazor/ant-design-blazor/commit/53c1285) [@Andrzej Bakun](https://github.com/Andrzej Bakun)
|
||||
- 🐞 修复 DisabledDate 的问题。[#1298](https://github.com/ant-design-blazor/ant-design-blazor/pull/1298) [@mutouzdl](https://github.com/mutouzdl)
|
||||
- 🆕 FormITem 增加 LabelTemplate 模板。[#1293](https://github.com/ant-design-blazor/ant-design-blazor/pull/1293) [@ldsenow](https://github.com/ldsenow)
|
||||
- 🐞 修复当 Value 和 DefaultValue 同时设置时,Value 会被 DefaultValue 覆盖的问题。[5f14377](https://github.com/ant-design-blazor/ant-design-blazor/commit/5f14377) [@Andrzej Bakun](https://github.com/Andrzej Bakun)
|
||||
- 📖 修复表格路由分页示例。[#1313](https://github.com/ant-design-blazor/ant-design-blazor/pull/1313) [@Zonciu](https://github.com/Zonciu)
|
||||
|
||||
## 0.7.3
|
||||
|
||||
`2021-03-29`
|
||||
|
||||
- 🐞 修复 Dropdown 下拉列表动画反向的问题。[#1274](https://github.com/ant-design/ant-design/pull/1274) [@mutouzdl](https://github.com/mutouzdl)
|
||||
- 🐞 修正 Tree 组件节点无法展开的问题。[#1275](https://github.com/ant-design/ant-design/pull/1275) [@TimChen44](https://github.com/TimChen44)
|
||||
- 💄 修复 Cascader 不能通过 Style 属性影响的样式的问题。[#1269](https://github.com/ant-design/ant-design/pull/1269) [@ElderJames](https://github.com/ElderJames)
|
||||
- 🐞 修复 DatePicker [从结束日期面板选择的日期]、[季度面板的日期范围效果] 不正确。[#1260](https://github.com/ant-design/ant-design/pull/1260) [@mutouzdl](https://github.com/mutouzdl)
|
||||
- 📖 增加 .NET Foundation 版权信息。[#1272](https://github.com/ant-design/ant-design/pull/1272) [@ElderJames](https://github.com/ElderJames)
|
||||
- 📖 修复样式同步和 PR 预览的脚本。[68c7539](https://github.com/ant-design/ant-design/commit/68c7539) [@ElderJames](https://github.com/ElderJames)
|
||||
- 🐞 修复 Dropdown 下拉列表动画反向的问题。[#1274](https://github.com/ant-design-blazor/ant-design-blazor/pull/1274) [@mutouzdl](https://github.com/mutouzdl)
|
||||
- 🐞 修正 Tree 组件节点无法展开的问题。[#1275](https://github.com/ant-design-blazor/ant-design-blazor/pull/1275) [@TimChen44](https://github.com/TimChen44)
|
||||
- 💄 修复 Cascader 不能通过 Style 属性影响的样式的问题。[#1269](https://github.com/ant-design-blazor/ant-design-blazor/pull/1269) [@ElderJames](https://github.com/ElderJames)
|
||||
- 🐞 修复 DatePicker [从结束日期面板选择的日期]、[季度面板的日期范围效果] 不正确。[#1260](https://github.com/ant-design-blazor/ant-design-blazor/pull/1260) [@mutouzdl](https://github.com/mutouzdl)
|
||||
- 📖 增加 .NET Foundation 版权信息。[#1272](https://github.com/ant-design-blazor/ant-design-blazor/pull/1272) [@ElderJames](https://github.com/ElderJames)
|
||||
- 📖 修复样式同步和 PR 预览的脚本。[68c7539](https://github.com/ant-design-blazor/ant-design-blazor/commit/68c7539) [@ElderJames](https://github.com/ElderJames)
|
||||
|
||||
## 0.7.2
|
||||
|
||||
|
@ -6,6 +6,8 @@ namespace AntDesign
|
||||
public static class DateHelper
|
||||
{
|
||||
private static readonly System.Globalization.Calendar _calendar = CultureInfo.InvariantCulture.Calendar;
|
||||
private const int DECADE_YEAR_COUNT = 10;
|
||||
private const int QUARTER_MONTH_COUNT = 3;
|
||||
|
||||
public static bool IsSameDate(DateTime date, DateTime compareDate)
|
||||
{
|
||||
@ -43,10 +45,21 @@ namespace AntDesign
|
||||
|
||||
public static string GetDayOfQuarter(DateTime date)
|
||||
{
|
||||
int offset = date.Month % 3 > 0 ? 1 : 0;
|
||||
int quarter = date.Month / 3 + offset;
|
||||
return $"Q{GetQuarter(date)}";
|
||||
}
|
||||
|
||||
return $"Q{quarter}";
|
||||
public static int GetQuarter(DateTime date)
|
||||
{
|
||||
int offset = date.Month % QUARTER_MONTH_COUNT > 0 ? 1 : 0;
|
||||
int quarter = date.Month / QUARTER_MONTH_COUNT + offset;
|
||||
|
||||
return quarter;
|
||||
}
|
||||
|
||||
public static DateTime GetStartDateOfQuarter(DateTime date)
|
||||
{
|
||||
int quarter = GetQuarter(date);
|
||||
return new DateTime(date.Year, 1 + ((quarter - 1) * QUARTER_MONTH_COUNT), 1);
|
||||
}
|
||||
|
||||
public static int GetWeekOfYear(DateTime date)
|
||||
@ -54,6 +67,78 @@ namespace AntDesign
|
||||
return _calendar.GetWeekOfYear(date, CalendarWeekRule.FirstDay, DayOfWeek.Monday);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// for example,
|
||||
/// when currentDateTime is 2020-01-04 05:34:55 then:
|
||||
/// the next date shouble be 2030-01-01 00:00:00, it's the start date of next 10 years
|
||||
///
|
||||
/// when currentDateTime is 2023-01-04 05:34:55 then:
|
||||
/// the next date shouble be 2030-01-01 00:00:00, it's the start date of next 10 years
|
||||
///
|
||||
/// when currentDateTime is 2018-01-04 05:34:55 then:
|
||||
/// the next date shouble be 2020-01-01 00:00:00, it's the start date of next 10 years
|
||||
/// </summary>
|
||||
/// <param name="date"></param>
|
||||
/// <returns></returns>
|
||||
public static DateTime GetNextStartDateOfDecade(DateTime date)
|
||||
{
|
||||
int year = date.Year / DECADE_YEAR_COUNT * DECADE_YEAR_COUNT;
|
||||
|
||||
if (year < DateTime.MinValue.Year)
|
||||
{
|
||||
year = DateTime.MinValue.Year;
|
||||
}
|
||||
|
||||
return AddYearsSafely(new DateTime(year, 1, 1), DECADE_YEAR_COUNT);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// for example, when currentDateTime is 2020-01-04 05:34:55 then:
|
||||
/// the next date shouble be 2021-01-01 00:00:00, it's the start date of next year
|
||||
/// </summary>
|
||||
/// <param name="date"></param>
|
||||
/// <returns></returns>
|
||||
public static DateTime GetNextStartDateOfYear(DateTime date)
|
||||
{
|
||||
return AddYearsSafely(new DateTime(date.Year, 1, 1), 1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// for example, when currentDateTime is 2020-01-04 05:34:55 then:
|
||||
/// the next date shouble be 2020-04-01 00:00:00, it's the start date of the next quarter in 2020
|
||||
/// </summary>
|
||||
/// <param name="date"></param>
|
||||
/// <returns></returns>
|
||||
public static DateTime GetNextStartDateOfQuarter(DateTime date)
|
||||
{
|
||||
var nextQuarterDate = AddMonthsSafely(new DateTime(date.Year, date.Month, 1), QUARTER_MONTH_COUNT);
|
||||
|
||||
return GetStartDateOfQuarter(nextQuarterDate);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// for example, when currentDateTime is 2020-01-04 05:34:55 then:
|
||||
/// the next date shouble be 2020-02-01 00:00:00 , it's the start date of next month
|
||||
/// </summary>
|
||||
/// <param name="date"></param>
|
||||
/// <returns></returns>
|
||||
public static DateTime GetNextStartDateOfMonth(DateTime date)
|
||||
{
|
||||
return AddMonthsSafely(new DateTime(date.Year, date.Month, 1), 1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// for example, when currentDateTime is 2020-01-04 05:34:55 then:
|
||||
/// the next date shouble be 2021-01-05 00:00:00, it's the start date of next day
|
||||
/// </summary>
|
||||
/// <param name="date"></param>
|
||||
/// <returns></returns>
|
||||
public static DateTime GetNextStartDateOfDay(DateTime date)
|
||||
{
|
||||
return AddDaysSafely(new DateTime(date.Year, date.Month, date.Day), 1);
|
||||
}
|
||||
|
||||
|
||||
public static DateTime CombineNewDate(
|
||||
DateTime date,
|
||||
int? year = null,
|
||||
|
@ -78,7 +78,7 @@ export function getFileInfo(element) {
|
||||
var fileInfo = [];
|
||||
for (var i = 0; i < element.files.length; i++) {
|
||||
var file = element.files[i];
|
||||
var objectUrl = getObjectURL(element);
|
||||
var objectUrl = getObjectURL(file);
|
||||
fileInfo.push({
|
||||
fileName: file.name,
|
||||
size: file.size,
|
||||
@ -91,9 +91,8 @@ export function getFileInfo(element) {
|
||||
}
|
||||
}
|
||||
|
||||
export function getObjectURL(element) {
|
||||
export function getObjectURL(file: File) {
|
||||
var url = null;
|
||||
var file = element.files[0];
|
||||
if (window.URL != undefined) {
|
||||
url = window.URL.createObjectURL(file);
|
||||
} else if (window.webkitURL != undefined) {
|
||||
@ -511,6 +510,11 @@ export function getTextAreaInfo(element) {
|
||||
result["borderBottom"] = parseFloat(document.defaultView.getComputedStyle(element, null).getPropertyValue("border-bottom"));
|
||||
result["borderTop"] = parseFloat(document.defaultView.getComputedStyle(element, null).getPropertyValue("border-top"));
|
||||
}
|
||||
//Firefox can return this as NaN, so it has to be handled here like that.
|
||||
if (Object.is(NaN, result["borderTop"]))
|
||||
result["borderTop"] = 1;
|
||||
if (Object.is(NaN, result["borderBottom"]))
|
||||
result["borderBottom"] = 1;
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -615,16 +619,20 @@ function preventKeys(e, keys: string[]) {
|
||||
}
|
||||
|
||||
export function addPreventKeys(inputElement, keys: string[]) {
|
||||
let dom = getDom(inputElement);
|
||||
keys = keys.map(function (x) { return x.toUpperCase(); })
|
||||
funcDict[inputElement.id + "keydown"] = (e) => preventKeys(e, keys);
|
||||
(dom as HTMLElement).addEventListener("keydown", funcDict[inputElement.id + "keydown"], false);
|
||||
if (inputElement) {
|
||||
let dom = getDom(inputElement);
|
||||
keys = keys.map(function (x) { return x.toUpperCase(); })
|
||||
funcDict[inputElement.id + "keydown"] = (e) => preventKeys(e, keys);
|
||||
(dom as HTMLElement).addEventListener("keydown", funcDict[inputElement.id + "keydown"], false);
|
||||
}
|
||||
}
|
||||
|
||||
export function removePreventKeys(inputElement) {
|
||||
let dom = getDom(inputElement);
|
||||
(dom as HTMLElement).removeEventListener("keydown", funcDict[inputElement.id + "keydown"]);
|
||||
funcDict[inputElement.id + "keydown"] = null;
|
||||
if (inputElement) {
|
||||
let dom = getDom(inputElement);
|
||||
(dom as HTMLElement).removeEventListener("keydown", funcDict[inputElement.id + "keydown"]);
|
||||
funcDict[inputElement.id + "keydown"] = null;
|
||||
}
|
||||
}
|
||||
|
||||
function preventKeyOnCondition(e, key: string, check: () => boolean) {
|
||||
@ -635,15 +643,19 @@ function preventKeyOnCondition(e, key: string, check: () => boolean) {
|
||||
}
|
||||
|
||||
export function addPreventEnterOnOverlayVisible(element, overlayElement) {
|
||||
let dom = getDom(element);
|
||||
funcDict[element.id + "keydown:Enter"] = (e) => preventKeyOnCondition(e, "enter", () => overlayElement.offsetParent !== null);
|
||||
(dom as HTMLElement).addEventListener("keydown", funcDict[element.id + "keydown:Enter"], false);
|
||||
if (element && overlayElement) {
|
||||
let dom = getDom(element);
|
||||
funcDict[element.id + "keydown:Enter"] = (e) => preventKeyOnCondition(e, "enter", () => overlayElement.offsetParent !== null);
|
||||
(dom as HTMLElement).addEventListener("keydown", funcDict[element.id + "keydown:Enter"], false);
|
||||
}
|
||||
}
|
||||
|
||||
export function removePreventEnterOnOverlayVisible(element) {
|
||||
let dom = getDom(element);
|
||||
(dom as HTMLElement).removeEventListener("keydown", funcDict[element.id + "keydown:Enter"]);
|
||||
funcDict[element.id + "keydown:Enter"] = null;
|
||||
if (element) {
|
||||
let dom = getDom(element);
|
||||
(dom as HTMLElement).removeEventListener("keydown", funcDict[element.id + "keydown:Enter"]);
|
||||
funcDict[element.id + "keydown:Enter"] = null;
|
||||
}
|
||||
}
|
||||
|
||||
export function setDomAttribute(element, attributes) {
|
||||
|
@ -174,12 +174,7 @@ namespace AntDesign.Internal
|
||||
string selectedCls = isSelected ? $"{PrefixCls}-cell-selected" : "";
|
||||
string inRangeCls = isInRange ? $"{PrefixCls}-cell-in-range" : "";
|
||||
|
||||
string disabledCls = "";
|
||||
if (DisabledDate != null && DisabledDate(currentColDate))
|
||||
{
|
||||
disabledCls = $"{PrefixCls}-cell-disabled";
|
||||
}
|
||||
|
||||
string disabledCls = GetDisabledCls(currentColDate);
|
||||
string rangeStartCls = GetRangeStartCls(currentColDate);
|
||||
string rangeEndCls = GetRangeEndCls(currentColDate);
|
||||
string rangeHoverCls = GetRangeHoverCls(currentColDate);
|
||||
@ -418,6 +413,20 @@ namespace AntDesign.Internal
|
||||
return cls.ToString();
|
||||
}
|
||||
|
||||
private string GetDisabledCls(DateTime currentColDate)
|
||||
{
|
||||
string disabledCls = "";
|
||||
|
||||
var nextStartDate = GetNextStartDate(currentColDate);
|
||||
|
||||
if (DisabledDate?.Invoke(DateHelper.AddDaysSafely(nextStartDate, -1)) == true)
|
||||
{
|
||||
disabledCls = $"{PrefixCls}-cell-disabled";
|
||||
}
|
||||
|
||||
return disabledCls;
|
||||
}
|
||||
|
||||
private DateTime? FormatDateByPicker(DateTime? dateTime)
|
||||
{
|
||||
return DateHelper.FormatDateByPicker(dateTime, Picker);
|
||||
@ -459,6 +468,21 @@ namespace AntDesign.Internal
|
||||
};
|
||||
}
|
||||
|
||||
private DateTime GetNextStartDate(DateTime currentDateTime)
|
||||
{
|
||||
return Picker switch
|
||||
{
|
||||
DatePickerType.Decade => DateHelper.GetNextStartDateOfDecade(currentDateTime),
|
||||
DatePickerType.Year => DateHelper.GetNextStartDateOfYear(currentDateTime),
|
||||
DatePickerType.Quarter => DateHelper.GetNextStartDateOfQuarter(currentDateTime),
|
||||
DatePickerType.Month => DateHelper.GetNextStartDateOfMonth(currentDateTime),
|
||||
DatePickerType.Week => DateHelper.GetNextStartDateOfDay(currentDateTime),
|
||||
DatePickerType.Date => DateHelper.GetNextStartDateOfDay(currentDateTime),
|
||||
DatePickerType.Time => DateHelper.GetNextStartDateOfDay(currentDateTime),
|
||||
_ => currentDateTime,
|
||||
};
|
||||
}
|
||||
|
||||
private bool ShouldStopRenderDate(DateTime preDate, DateTime nextDate)
|
||||
{
|
||||
return Picker switch
|
||||
|
@ -2,11 +2,18 @@
|
||||
@inherits AntDomComponentBase
|
||||
@using AntDesign.Internal;
|
||||
|
||||
<Row Class="@ClassMapper.Class" Style="@Style" Id="@Id">
|
||||
@if (!string.IsNullOrEmpty(Label))
|
||||
<Row class="@ClassMapper.Class" style="@Style" id="@Id">
|
||||
@if (!string.IsNullOrEmpty(Label) || LabelTemplate != null)
|
||||
{
|
||||
<AntDesign.Col @attributes="GetLabelColAttributes()" Class="@_labelClassMapper.Class">
|
||||
<label class=@(Required ? $"{_prefixCls}-required" : _labelCls)> @(Label)</label>
|
||||
@if (LabelTemplate != null)
|
||||
{
|
||||
@LabelTemplate
|
||||
}
|
||||
else
|
||||
{
|
||||
<label class=@GetLabelClass()>@(Label)</label>
|
||||
}
|
||||
</AntDesign.Col>
|
||||
}
|
||||
<AntDesign.Col @attributes="GetWrapperColAttributes()" Class=@($"{_prefixCls}-control")>
|
||||
|
@ -31,6 +31,9 @@ namespace AntDesign
|
||||
[Parameter]
|
||||
public string Label { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public RenderFragment LabelTemplate { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public ColLayoutParam LabelCol { get; set; }
|
||||
|
||||
@ -183,6 +186,11 @@ namespace AntDesign
|
||||
return wrapperColParameter.ToAttributes();
|
||||
}
|
||||
|
||||
private string GetLabelClass()
|
||||
{
|
||||
return Required ? $"{_prefixCls}-required" : _labelCls;
|
||||
}
|
||||
|
||||
void IFormItem.AddControl<TValue>(AntInputComponentBase<TValue> control)
|
||||
{
|
||||
if (control.FieldIdentifier.Model == null)
|
||||
|
@ -1,6 +1,6 @@
|
||||
@namespace AntDesign
|
||||
@inherits AntDomComponentBase
|
||||
|
||||
<div class="@ClassMapper.Class" style="@GutterStyle @Style" id="@Id" @ref="Ref">
|
||||
<div class="@ClassMapper.Class" style="@GutterStyle @_hostFlexStyle @Style" id="@Id" @ref="Ref">
|
||||
@ChildContent
|
||||
</div>
|
||||
|
@ -63,7 +63,7 @@ namespace AntDesign
|
||||
[CascadingParameter]
|
||||
public Row Row { get; set; }
|
||||
|
||||
private string _hostFlexStyle = null;
|
||||
private string _hostFlexStyle;
|
||||
|
||||
private string GutterStyle { get; set; }
|
||||
|
||||
@ -105,11 +105,11 @@ namespace AntDesign
|
||||
}, embedded =>
|
||||
{
|
||||
ClassMapper
|
||||
.If($"{prefixCls}-{sizeName}-{embedded.Span.Value}", () => embedded.Span.Value != null)
|
||||
.If($"{prefixCls}-{sizeName}-order-{embedded.Order.Value}", () => embedded.Order.Value != null)
|
||||
.If($"{prefixCls}-{sizeName}-offset-{embedded.Offset.Value}", () => embedded.Offset.Value != null)
|
||||
.If($"{prefixCls}-{sizeName}-push-{embedded.Push.Value}", () => embedded.Push.Value != null)
|
||||
.If($"{prefixCls}-{sizeName}-pull-{embedded.Pull.Value}", () => embedded.Pull.Value != null);
|
||||
.GetIf(() => $"{prefixCls}-{sizeName}-{embedded.Span.Value}", () => embedded.Span.Value != null)
|
||||
.GetIf(() => $"{prefixCls}-{sizeName}-order-{embedded.Order.Value}", () => embedded.Order.Value != null)
|
||||
.GetIf(() => $"{prefixCls}-{sizeName}-offset-{embedded.Offset.Value}", () => embedded.Offset.Value != null)
|
||||
.GetIf(() => $"{prefixCls}-{sizeName}-push-{embedded.Push.Value}", () => embedded.Push.Value != null)
|
||||
.GetIf(() => $"{prefixCls}-{sizeName}-pull-{embedded.Pull.Value}", () => embedded.Pull.Value != null);
|
||||
});
|
||||
}
|
||||
|
||||
@ -122,12 +122,12 @@ namespace AntDesign
|
||||
{
|
||||
if (Regex.Match(str, "^\\d+(\\.\\d+)?(px|em|rem|%)$").Success)
|
||||
{
|
||||
return $"0 0 {Flex}";
|
||||
return $"flex: 0 0 {str}";
|
||||
}
|
||||
|
||||
return Flex.AsT0;
|
||||
return $"flex: {str}";
|
||||
},
|
||||
num => $"{Flex} {Flex} auto");
|
||||
num => $"flex: {num} {num} auto");
|
||||
}
|
||||
|
||||
protected override void OnInitialized()
|
||||
@ -147,4 +147,4 @@ namespace AntDesign
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -39,6 +39,9 @@ namespace AntDesign
|
||||
[Parameter]
|
||||
public string Justify { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public bool Wrap { get; set; } = true;
|
||||
|
||||
[Parameter]
|
||||
public GutterType Gutter { get; set; }
|
||||
|
||||
@ -79,6 +82,7 @@ namespace AntDesign
|
||||
.If($"{prefixCls}-center", () => Justify == "center")
|
||||
.If($"{prefixCls}-space-around", () => Justify == "space-around")
|
||||
.If($"{prefixCls}-space-between", () => Justify == "space-between")
|
||||
.If($"{prefixCls}-no-wrap", () => !Wrap)
|
||||
.If($"{prefixCls}-rtl", () => RTL)
|
||||
;
|
||||
|
||||
@ -176,4 +180,4 @@ namespace AntDesign
|
||||
sm,
|
||||
xs
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using AntDesign.JsInterop;
|
||||
@ -29,6 +30,9 @@ namespace AntDesign
|
||||
[Parameter]
|
||||
public bool AutoSize { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public bool DefaultToEmptyString { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public uint MinRows
|
||||
{
|
||||
@ -100,6 +104,37 @@ namespace AntDesign
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool TryParseValueFromString(string value, out string result, out string validationErrorMessage)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(value))
|
||||
{
|
||||
if (DefaultToEmptyString)
|
||||
result = string.Empty;
|
||||
else
|
||||
result = default;
|
||||
validationErrorMessage = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
var success = BindConverter.TryConvertTo<string>(
|
||||
value, CultureInfo.CurrentCulture, out var parsedValue);
|
||||
|
||||
if (success)
|
||||
{
|
||||
result = parsedValue;
|
||||
validationErrorMessage = null;
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = default;
|
||||
validationErrorMessage = $"{FieldIdentifier.FieldName} field isn't valid.";
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (AutoSize && !_isReloading)
|
||||
@ -176,4 +211,4 @@ namespace AntDesign
|
||||
public double BorderBottom { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -49,6 +49,7 @@ namespace AntDesign
|
||||
get { return _currentValue; }
|
||||
set
|
||||
{
|
||||
_valueWasSet = true;
|
||||
if (_currentValue != value)
|
||||
{
|
||||
this._currentValue = value;
|
||||
@ -80,24 +81,33 @@ namespace AntDesign
|
||||
|
||||
/// <summary>
|
||||
/// 是否允许半选
|
||||
/// Whether to allow half-selection
|
||||
/// </summary>
|
||||
private bool _hasHalf = false;
|
||||
|
||||
/// <summary>
|
||||
/// 鼠标悬停时从最左到光标位置的星星数。
|
||||
/// The number of stars from the far left to the cursor position when the hovered with mouse.
|
||||
/// </summary>
|
||||
private int _hoverValue = 0;
|
||||
|
||||
/// <summary>
|
||||
/// 当前被选中的星星数量
|
||||
/// Number of stars currently selected
|
||||
/// </summary>
|
||||
private decimal _currentValue;
|
||||
|
||||
/// <summary>
|
||||
/// 是否获取的输入焦点
|
||||
/// Wheter to get input focus.
|
||||
/// </summary>
|
||||
private bool _isFocused = false;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates if Value has been changed. Needed to avoid reseting to DefaultValue if exists.
|
||||
/// </summary>
|
||||
private bool _valueWasSet;
|
||||
|
||||
private void Blur(FocusEventArgs e)
|
||||
{
|
||||
this._isFocused = false;
|
||||
@ -169,7 +179,7 @@ namespace AntDesign
|
||||
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
if (DefaultValue > 0)
|
||||
if (DefaultValue > 0 && !_valueWasSet)
|
||||
{
|
||||
this.Value = DefaultValue;
|
||||
}
|
||||
|
@ -111,7 +111,7 @@
|
||||
</div>
|
||||
</Overlay>
|
||||
<Unbound>
|
||||
<CascadingValue Value="this" Name=@("ParentSelect") IsFixed="true">
|
||||
<CascadingValue Value="this" Name=@("ParentSelect") IsFixed>
|
||||
<CascadingValue Value="@LabelTemplate" Name="ParentLabelTemplate">
|
||||
<CascadingValue Value="@ShowSearchIcon" Name="ShowSearchIcon">
|
||||
<CascadingValue Value="@ShowArrowIcon" Name="ShowArrowIcon">
|
||||
|
@ -167,7 +167,7 @@ namespace AntDesign
|
||||
else
|
||||
{
|
||||
SelectOptionItems.Clear();
|
||||
|
||||
SelectedOptionItems.Clear();
|
||||
Value = default;
|
||||
|
||||
_datasource = null;
|
||||
@ -180,6 +180,7 @@ namespace AntDesign
|
||||
if (value != null && !value.Any() && SelectOptionItems.Any())
|
||||
{
|
||||
SelectOptionItems.Clear();
|
||||
SelectedOptionItems.Clear();
|
||||
|
||||
Value = default;
|
||||
|
||||
@ -541,6 +542,8 @@ namespace AntDesign
|
||||
if (exists is null)
|
||||
{
|
||||
SelectOptionItems.Remove(selectOption);
|
||||
if (selectOption.IsSelected)
|
||||
SelectedOptionItems.Remove(selectOption);
|
||||
}
|
||||
else
|
||||
dataStoreToSelectOptionItemsMatch.Add(exists, selectOption);
|
||||
@ -548,6 +551,14 @@ namespace AntDesign
|
||||
}
|
||||
}
|
||||
|
||||
//A simple approach to avoid unnecessary scanning through _selectedValues once
|
||||
//all of SelectOptionItem where already marked as selected
|
||||
int processedSelectedCount = 0;
|
||||
if (SelectMode == SelectMode.Default && _selectedValue != null)
|
||||
processedSelectedCount = 1;
|
||||
else if (SelectMode != SelectMode.Default && _selectedValues != null)
|
||||
processedSelectedCount = _selectedValues.Count();
|
||||
|
||||
foreach (var item in _datasource)
|
||||
{
|
||||
TItemValue value = _getValue(item);
|
||||
@ -571,6 +582,15 @@ namespace AntDesign
|
||||
var groupName = string.Empty;
|
||||
var label = _getLabel(item);
|
||||
|
||||
bool isSelected = false;
|
||||
if (processedSelectedCount > 0)
|
||||
{
|
||||
if (SelectMode == SelectMode.Default)
|
||||
isSelected = value.Equals(_selectedValue);
|
||||
else
|
||||
isSelected = _selectedValues.Contains(value);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(DisabledName))
|
||||
disabled = _getDisabled(item);
|
||||
|
||||
@ -585,16 +605,33 @@ namespace AntDesign
|
||||
GroupName = groupName,
|
||||
IsDisabled = disabled,
|
||||
Item = item,
|
||||
Value = value
|
||||
Value = value,
|
||||
IsSelected = isSelected,
|
||||
IsHidden = isSelected && HideSelected
|
||||
};
|
||||
|
||||
SelectOptionItems.Add(newItem);
|
||||
if (isSelected)
|
||||
{
|
||||
processedSelectedCount--;
|
||||
SelectedOptionItems.Add(newItem);
|
||||
}
|
||||
}
|
||||
else if (exists && !IgnoreItemChanges)
|
||||
{
|
||||
updateSelectOption.Label = label;
|
||||
updateSelectOption.IsDisabled = disabled;
|
||||
updateSelectOption.GroupName = groupName;
|
||||
updateSelectOption.IsHidden = isSelected && HideSelected;
|
||||
if (isSelected)
|
||||
{
|
||||
if (!updateSelectOption.IsSelected)
|
||||
{
|
||||
updateSelectOption.IsSelected = isSelected;
|
||||
SelectedOptionItems.Add(updateSelectOption);
|
||||
}
|
||||
processedSelectedCount--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1171,7 +1208,8 @@ namespace AntDesign
|
||||
/// </summary>
|
||||
internal async Task UpdateOverlayPositionAsync()
|
||||
{
|
||||
await _dropDown.GetOverlayComponent().UpdatePosition();
|
||||
if (_dropDown.Visible)
|
||||
await _dropDown.GetOverlayComponent().UpdatePosition();
|
||||
}
|
||||
|
||||
#region Events
|
||||
|
@ -5,38 +5,38 @@
|
||||
@{
|
||||
bool showPrefixAsSeparate = false;
|
||||
bool showPrefixInSelected = false;
|
||||
|
||||
|
||||
if (ParentSelect.PrefixIcon != null)
|
||||
{
|
||||
showPrefixAsSeparate = ParentSelect.PrefixIcon != null && !(ParentSelect.SelectMode != SelectMode.Default && ParentSelect.SelectedOptionItems.Any());
|
||||
showPrefixInSelected = !showPrefixAsSeparate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
<div class="@Prefix-selector" @ref="@Ref" style="@(ParentSelect.PrefixIcon is null?"":"padding-left: 4px;")">
|
||||
@if (showPrefixAsSeparate)
|
||||
{
|
||||
<span class="@Prefix-prefix" unselectable="on" aria-hidden="true" style="user-select: none;display:flex;align-items: center;padding-right: 4px;" >
|
||||
<span class="@Prefix-prefix" unselectable="on" aria-hidden="true" style="user-select: none;display:flex;align-items: center;padding-right: 4px;">
|
||||
@ParentSelect.PrefixIcon
|
||||
</span>
|
||||
</span>
|
||||
}
|
||||
<div style="display: flex;position: relative;flex-grow: 1;flex-wrap: wrap;align-items: center;">
|
||||
@if (ShowPlaceholder)
|
||||
{
|
||||
{
|
||||
@if (showPrefixAsSeparate)
|
||||
{
|
||||
<span class="@Prefix-selection-placeholder" style="left: 0px;">@Placeholder</span>
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
<span class="@Prefix-selection-placeholder">@Placeholder</span>
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@if (ParentSelect.SelectMode == SelectMode.Default)
|
||||
{
|
||||
{
|
||||
var selectedItem = ParentSelect.SelectedOptionItems.FirstOrDefault();
|
||||
//Console.WriteLine($"({ParentSelect.Id}): {selectedItem.Value} => {selectedItem.Label}");
|
||||
if (string.IsNullOrEmpty(SearchValue) && selectedItem != null)
|
||||
@ -44,13 +44,13 @@
|
||||
@if (ParentLabelTemplate != null)
|
||||
{
|
||||
<CascadingValue Value="this" Name="SelectContent">
|
||||
<CascadingValue Value="@selectedItem" Name="SelectOption">
|
||||
@ParentLabelTemplate(selectedItem.Item)
|
||||
<CascadingValue Value="@selectedItem" Name="SelectOption">
|
||||
@ParentLabelTemplate(selectedItem.Item)
|
||||
</CascadingValue>
|
||||
</CascadingValue>
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
<span class="@Prefix-selection-item">
|
||||
<span class="@Prefix-selection-item-content">@selectedItem.Label</span>
|
||||
</span>
|
||||
@ -61,31 +61,31 @@
|
||||
{
|
||||
var selectedItems = ParentSelect.SelectedOptionItems;
|
||||
|
||||
@if (showPrefixInSelected)
|
||||
@if (showPrefixInSelected)
|
||||
{
|
||||
<span class="@Prefix-prefix" unselectable="on" aria-hidden="true" style="user-select: none;display:flex;align-items: center;padding-right: 4px;" >
|
||||
<span class="@Prefix-prefix" unselectable="on" aria-hidden="true" style="user-select: none;display:flex;align-items: center;padding-right: 4px;">
|
||||
@ParentSelect.PrefixIcon
|
||||
</span>
|
||||
}
|
||||
}
|
||||
@foreach (var selectedOption in selectedItems)
|
||||
{
|
||||
@if (ParentLabelTemplate != null)
|
||||
{
|
||||
<CascadingValue Value="this" Name="SelectContent">
|
||||
<CascadingValue Value="@selectedOption" Name="SelectOption">
|
||||
@ParentLabelTemplate(selectedOption.Item)
|
||||
</CascadingValue>
|
||||
@ParentLabelTemplate(selectedOption.Item)
|
||||
</CascadingValue>
|
||||
</CascadingValue>
|
||||
}
|
||||
else
|
||||
{
|
||||
<span class="@Prefix-selection-item">
|
||||
<span class="@Prefix-selection-item-content">@selectedOption.Label</span>
|
||||
<span unselectable="on" aria-hidden="true" style="user-select: none;" class="@Prefix-selection-item-remove"
|
||||
@onclick="()=> OnRemoveSelected.InvokeAsync(selectedOption)" @onclick:stopPropagation="true">
|
||||
@onmousedown="()=> OnRemoveSelected.InvokeAsync(selectedOption)" onclick="event.stopPropagation()">
|
||||
<Icon Type="close"></Icon>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -93,25 +93,25 @@
|
||||
|
||||
<span class="@Prefix-selection-search" style="@_inputWidth">
|
||||
<input @ref="ParentSelect._inputRef"
|
||||
@oninput="OnInput"
|
||||
@onkeyup="OnKeyUp"
|
||||
@onkeydown="OnKeyDown"
|
||||
@onfocus="OnFocus"
|
||||
@onblur="OnBlur"
|
||||
@attributes=@AdditonalAttributes()
|
||||
@onkeypress="@OnKeyPressEventHandler"
|
||||
@onkeypress:preventDefault="@_suppressInput"
|
||||
@onkeypress:stopPropagation="true"
|
||||
@bind-value="@SearchValue"
|
||||
id="@ParentSelect.Id"
|
||||
role="combobox"
|
||||
class="@Prefix-selection-search-input"
|
||||
autocomplete="off"
|
||||
aria-owns="@(ParentSelect.Id)_list"
|
||||
aria-expanded="@IsOverlayShow"
|
||||
aria-autocomplete="list"
|
||||
aria-controls="@(ParentSelect.Id)_list"
|
||||
style="@_inputStyle"/>
|
||||
@oninput="OnInput"
|
||||
@onkeyup="OnKeyUp"
|
||||
@onkeydown="OnKeyDown"
|
||||
@onfocus="OnFocus"
|
||||
@onblur="OnBlur"
|
||||
@attributes=@AdditonalAttributes()
|
||||
@onkeypress="@OnKeyPressEventHandler"
|
||||
@onkeypress:preventDefault="@_suppressInput"
|
||||
@onkeypress:stopPropagation="true"
|
||||
@bind-value="@SearchValue"
|
||||
id="@ParentSelect.Id"
|
||||
role="combobox"
|
||||
class="@Prefix-selection-search-input"
|
||||
autocomplete="off"
|
||||
aria-owns="@(ParentSelect.Id)_list"
|
||||
aria-expanded="@IsOverlayShow"
|
||||
aria-autocomplete="list"
|
||||
aria-controls="@(ParentSelect.Id)_list"
|
||||
style="@_inputStyle"/>
|
||||
|
||||
@if (ParentSelect.SelectMode != SelectMode.Default)
|
||||
{
|
||||
@ -165,7 +165,7 @@
|
||||
}
|
||||
</span>
|
||||
}
|
||||
|
||||
|
||||
@if (!ParentSelect.Disabled && ParentSelect.AllowClear && ParentSelect.HasValue)
|
||||
{
|
||||
<span class="ant-select-clear" unselectable="on" aria-hidden="true" style="user-select: none;" @onclick="OnClearClick" @onclick:stopPropagation="true">
|
||||
@ -182,6 +182,12 @@ else
|
||||
@ParentSelect.SuffixIcon
|
||||
</span>
|
||||
}
|
||||
else if (ParentSelect.Loading)
|
||||
{
|
||||
<span class="ant-select-arrow ant-select-arrow-loading" unselectable="on" aria-hidden="true" style="user-select: none;">
|
||||
<Icon Type="loading"></Icon>
|
||||
</span>
|
||||
}
|
||||
@if (!ParentSelect.Disabled && ParentSelect.AllowClear && ParentSelect.HasValue)
|
||||
{
|
||||
<span class="ant-select-clear" unselectable="on" aria-hidden="true" style="user-select: none;" @onclick="OnClearClick" @onclick:stopPropagation="true">
|
||||
|
@ -15,6 +15,11 @@ else if (IsMeasure)
|
||||
}
|
||||
else if (IsColGroup)
|
||||
{
|
||||
@if (AppendExpandColumn)
|
||||
{
|
||||
<col class="ant-table-expand-icon-col">
|
||||
}
|
||||
|
||||
if (Width != null)
|
||||
{
|
||||
<col style="width: @((CssSizeLength)Width); min-width: @((CssSizeLength)Width);">
|
||||
@ -26,13 +31,42 @@ else if (IsColGroup)
|
||||
}
|
||||
else if (IsHeader && HeaderColSpan != 0)
|
||||
{
|
||||
@if (AppendExpandColumn)
|
||||
{
|
||||
<th class="ant-table-cell ant-table-row-expand-icon-cell"></th>
|
||||
}
|
||||
|
||||
<th class="@ClassMapper.Class" style="@FixedStyle @HeaderStyle" colspan="@HeaderColSpan">
|
||||
@if (TitleTemplate != null)@TitleTemplate else @Title
|
||||
</th>
|
||||
}
|
||||
else if (!IsHeader && RowSpan != 0 && ColSpan != 0)
|
||||
{
|
||||
@if (AppendExpandColumn)
|
||||
{
|
||||
<td class="ant-table-cell ant-table-row-expand-icon-cell">
|
||||
@if (Table.RowExpandable(RowData) && (!Table.TreeMode || !RowData.HasChildren))
|
||||
{
|
||||
<button type="button" @onclick="ToggleTreeNode"
|
||||
class="ant-table-row-expand-icon @(RowData.Expanded?"ant-table-row-expand-icon-expanded":"ant-table-row-expand-icon-collapsed")"
|
||||
aria-label="@(RowData.Expanded?Table.Locale.Collapse:Table.Locale.Expand)"></button>
|
||||
}
|
||||
</td>
|
||||
}
|
||||
|
||||
<td class="@ClassMapper.Class" style="@FixedStyle @Style" rowspan="@RowSpan" colspan="@ColSpan">
|
||||
@if (ColIndex == Table.TreeExpandIconColumnIndex && Table.TreeMode)
|
||||
{
|
||||
<span class="ant-table-row-indent indent-level-@RowData.Level" style="padding-left: @((CssSizeLength)(RowData.Level * Table.IndentSize));"></span>
|
||||
@if (RowData.HasChildren)
|
||||
{
|
||||
<button type="button" @onclick="ToggleTreeNode" class="ant-table-row-expand-icon @(RowData?.Expanded==true?"ant-table-row-expand-icon-expanded":"ant-table-row-expand-icon-collapsed")" aria-label="@(RowData?.Expanded==true?Table.Locale.Collapse:Table.Locale.Expand)"></button>
|
||||
}
|
||||
else
|
||||
{
|
||||
<button type="button" class="ant-table-row-expand-icon ant-table-row-expand-icon-spaced" aria-label="@Table.Locale.Expand"></button>
|
||||
}
|
||||
}
|
||||
@ChildContent
|
||||
</td>
|
||||
}
|
@ -102,11 +102,11 @@ else if (IsBody && RowSpan != 0 && ColSpan != 0)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(Format))
|
||||
{
|
||||
@(Formatter<TData>.Format(GetValue != null ? GetValue(RowData) : Field, Format))
|
||||
@(Formatter<TData>.Format(Field, Format))
|
||||
}
|
||||
else
|
||||
{
|
||||
@(GetValue != null ? GetValue(RowData) : Field)
|
||||
@Field
|
||||
}
|
||||
}
|
||||
</td>
|
||||
|
@ -2,7 +2,9 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using AntDesign.Core.Reflection;
|
||||
using AntDesign.Internal;
|
||||
using AntDesign.TableModels;
|
||||
@ -25,7 +27,22 @@ namespace AntDesign
|
||||
public RenderFragment<TData> CellRender { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public TData Field { get; set; }
|
||||
public TData Field
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetValue != null ? GetValue(RowData) : _field;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (GetValue == null)
|
||||
{
|
||||
_field = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private TData _field;
|
||||
|
||||
[Parameter]
|
||||
public string DataIndex { get; set; }
|
||||
@ -75,11 +92,9 @@ namespace AntDesign
|
||||
[Parameter]
|
||||
public Expression<Func<TData, TData, bool>> OnFilter { get; set; }
|
||||
|
||||
private PropertyReflector? _propertyReflector;
|
||||
public string DisplayName { get; private set; }
|
||||
|
||||
public string DisplayName => _propertyReflector?.DisplayName;
|
||||
|
||||
public string FieldName => _propertyReflector?.PropertyName;
|
||||
public string FieldName { get; private set; }
|
||||
|
||||
public ITableSortModel SortModel { get; private set; }
|
||||
|
||||
@ -89,12 +104,16 @@ namespace AntDesign
|
||||
|
||||
public Func<RowData, TData> GetValue { get; private set; }
|
||||
|
||||
public LambdaExpression GetFieldExpression { get; private set; }
|
||||
|
||||
void IFieldColumn.ClearSorter() => SetSorter(SortDirection.None);
|
||||
|
||||
private static readonly EventCallbackFactory _callbackFactory = new EventCallbackFactory();
|
||||
|
||||
private bool _filterOpened;
|
||||
|
||||
private bool _hasFilterSelected;
|
||||
|
||||
private string[] _selectedFilterValues;
|
||||
|
||||
private ElementReference _filterTriggerRef;
|
||||
@ -109,19 +128,26 @@ namespace AntDesign
|
||||
{
|
||||
if (FieldExpression != null)
|
||||
{
|
||||
_propertyReflector = PropertyReflector.Create(FieldExpression);
|
||||
var paramExp = Expression.Parameter(ItemType);
|
||||
var member = ColumnExpressionHelper.GetReturnMemberInfo(FieldExpression);
|
||||
var bodyExp = Expression.MakeMemberAccess(paramExp, member);
|
||||
GetFieldExpression = Expression.Lambda(bodyExp, paramExp);
|
||||
}
|
||||
else if (DataIndex != null)
|
||||
{
|
||||
(_, GetFieldExpression) = ColumnDataIndexHelper<TData>.GetDataIndexConfig(this);
|
||||
}
|
||||
|
||||
if (Sortable)
|
||||
if (Sortable && GetFieldExpression != null)
|
||||
{
|
||||
if (_propertyReflector.HasValue)
|
||||
{
|
||||
SortModel = new SortModel<TData>(_propertyReflector.Value.PropertyInfo, SorterMultiple, DefaultSortOrder, SorterCompare);
|
||||
}
|
||||
else
|
||||
{
|
||||
(GetValue, SortModel) = ColumnDataIndexHelper<TData>.GetDataIndexConfig(this);
|
||||
}
|
||||
SortModel = new SortModel<TData>(GetFieldExpression, SorterMultiple, DefaultSortOrder, SorterCompare);
|
||||
}
|
||||
|
||||
if (GetFieldExpression != null)
|
||||
{
|
||||
var member = ColumnExpressionHelper.GetReturnMemberInfo(GetFieldExpression);
|
||||
DisplayName = member.GetCustomAttribute<DisplayNameAttribute>(true)?.DisplayName ?? member.Name;
|
||||
FieldName = member.Name;
|
||||
}
|
||||
}
|
||||
else if (IsBody)
|
||||
@ -137,8 +163,8 @@ namespace AntDesign
|
||||
_sortDirection = SortModel?.SortDirection ?? DefaultSortOrder ?? SortDirection.None;
|
||||
|
||||
ClassMapper
|
||||
.If("ant-table-column-has-sorters", () => Sortable)
|
||||
.If($"ant-table-column-sort", () => Sortable && SortModel != null && SortModel.SortDirection.IsIn(SortDirection.Ascending, SortDirection.Descending));
|
||||
.If("ant-table-column-has-sorters", () => Sortable)
|
||||
.If($"ant-table-column-sort", () => Sortable && SortModel != null && SortModel.SortDirection.IsIn(SortDirection.Ascending, SortDirection.Descending));
|
||||
}
|
||||
|
||||
private void HandleSort()
|
||||
@ -219,7 +245,7 @@ namespace AntDesign
|
||||
_filterOpened = false;
|
||||
_hasFilterSelected = Filters?.Any(x => x.Selected) == true;
|
||||
|
||||
FilterModel = _hasFilterSelected ? new FilterModel<TData>(_propertyReflector.Value.PropertyInfo, OnFilter, Filters.Where(x => x.Selected).ToList()) : null;
|
||||
FilterModel = _hasFilterSelected ? new FilterModel<TData>(GetFieldExpression, OnFilter, Filters.Where(x => x.Selected).ToList()) : null;
|
||||
|
||||
Table?.ReloadAndInvokeChange();
|
||||
}
|
||||
@ -230,4 +256,4 @@ namespace AntDesign
|
||||
FilterConfirm();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -171,5 +171,11 @@ namespace AntDesign
|
||||
|
||||
return $"position: sticky; {Fixed}: {(fixedWidths.Any() ? $"calc({string.Join(" + ", fixedWidths) })" : "0px")};";
|
||||
}
|
||||
|
||||
protected void ToggleTreeNode()
|
||||
{
|
||||
RowData.Expanded = !RowData.Expanded;
|
||||
Table?.Refresh();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,9 +27,9 @@ namespace AntDesign.Internal
|
||||
|
||||
private static ColumnCacheItem CreateDataIndexConfig(ColumnCacheKey key)
|
||||
{
|
||||
var (itemType, propType, dataIndex, sortable, sort, sorterMultiple, sorterCompare) = key;
|
||||
var (itemType, propType, dataIndex) = key;
|
||||
Func<RowData, TProp> getValue = null;
|
||||
ITableSortModel sortModel = null;
|
||||
LambdaExpression getFieldExpression = null;
|
||||
var properties = dataIndex?.Split(".");
|
||||
if (properties is {Length: > 0})
|
||||
{
|
||||
@ -40,21 +40,17 @@ namespace AntDesign.Internal
|
||||
var rowData1Exp = Expression.TypeAs(rowDataExp, rowData1Type);
|
||||
var dataMemberExp = Expression.Property(rowData1Exp, nameof(RowData<object>.Data));
|
||||
|
||||
Expression memberExp = canBeNull
|
||||
? dataMemberExp.AccessNullableProperty(properties)
|
||||
: dataMemberExp.AccessProperty(properties);
|
||||
var memberExp = canBeNull
|
||||
? dataMemberExp.AccessNullableProperty(properties)
|
||||
: dataMemberExp.AccessProperty(properties);
|
||||
getValue = Expression.Lambda<Func<RowData, TProp>>(memberExp, rowDataExp).Compile();
|
||||
|
||||
if (sortable)
|
||||
{
|
||||
var propertySelector = canBeNull
|
||||
? itemType.BuildAccessNullablePropertyLambdaExpression(properties)
|
||||
: itemType.BuildAccessPropertyLambdaExpression(properties);
|
||||
sortModel = new DataIndexSortModel<TProp>(dataIndex, propertySelector, sorterMultiple, sort, sorterCompare);
|
||||
}
|
||||
getFieldExpression = canBeNull
|
||||
? itemType.BuildAccessNullablePropertyLambdaExpression(properties)
|
||||
: itemType.BuildAccessPropertyLambdaExpression(properties);
|
||||
}
|
||||
|
||||
return new ColumnCacheItem(getValue, sortModel);
|
||||
return new ColumnCacheItem(getValue, getFieldExpression);
|
||||
}
|
||||
|
||||
internal readonly struct ColumnCacheKey
|
||||
@ -65,39 +61,23 @@ namespace AntDesign.Internal
|
||||
|
||||
internal readonly string DataIndex;
|
||||
|
||||
internal readonly bool Sortable;
|
||||
|
||||
internal readonly SortDirection DefaultSortOrder;
|
||||
|
||||
internal readonly int SorterMultiple;
|
||||
|
||||
internal readonly Func<TProp, TProp, int> SorterCompare;
|
||||
|
||||
internal static ColumnCacheKey Create(Column<TProp> column)
|
||||
{
|
||||
return new(column.ItemType, typeof(TProp), column.DataIndex, column.Sortable, column.DefaultSortOrder, column.SorterMultiple, column.SorterCompare);
|
||||
return new(column.ItemType, typeof(TProp), column.DataIndex);
|
||||
}
|
||||
|
||||
internal ColumnCacheKey(Type itemType, Type propType, string dataIndex, bool sortable, SortDirection defaultSortOrder, int sorterMultiple, Func<TProp, TProp, int> sorterCompare)
|
||||
internal ColumnCacheKey(Type itemType, Type propType, string dataIndex)
|
||||
{
|
||||
ItemType = itemType;
|
||||
PropType = propType;
|
||||
DataIndex = dataIndex;
|
||||
Sortable = sortable;
|
||||
DefaultSortOrder = defaultSortOrder;
|
||||
SorterMultiple = sorterMultiple;
|
||||
SorterCompare = sorterCompare;
|
||||
}
|
||||
|
||||
internal void Deconstruct(out Type itemType, out Type propType, out string dataIndex, out bool sortable, out SortDirection defaultSortOrder, out int sorterMultiple, out Func<TProp, TProp, int> sorterCompare)
|
||||
internal void Deconstruct(out Type itemType, out Type propType, out string dataIndex)
|
||||
{
|
||||
itemType = ItemType;
|
||||
propType = PropType;
|
||||
dataIndex = DataIndex;
|
||||
sortable = Sortable;
|
||||
defaultSortOrder = DefaultSortOrder;
|
||||
sorterMultiple = SorterMultiple;
|
||||
sorterCompare = SorterCompare;
|
||||
}
|
||||
}
|
||||
|
||||
@ -105,18 +85,18 @@ namespace AntDesign.Internal
|
||||
{
|
||||
internal readonly Func<RowData, TProp> GetValue;
|
||||
|
||||
internal readonly ITableSortModel SortModel;
|
||||
internal readonly LambdaExpression GetFieldExpression;
|
||||
|
||||
internal ColumnCacheItem(Func<RowData, TProp> getValue, ITableSortModel sortModel)
|
||||
internal ColumnCacheItem(Func<RowData, TProp> getValue, LambdaExpression getFieldExpression)
|
||||
{
|
||||
GetValue = getValue;
|
||||
SortModel = sortModel;
|
||||
GetFieldExpression = getFieldExpression;
|
||||
}
|
||||
|
||||
internal void Deconstruct(out Func<RowData, TProp> getValue, out ITableSortModel sortModel)
|
||||
internal void Deconstruct(out Func<RowData, TProp> getValue, out LambdaExpression getFieldExpression)
|
||||
{
|
||||
getValue = GetValue;
|
||||
sortModel = SortModel;
|
||||
getFieldExpression = GetFieldExpression;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
37
components/table/Internal/ColumnExpressionHelper.cs
Normal file
37
components/table/Internal/ColumnExpressionHelper.cs
Normal file
@ -0,0 +1,37 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
|
||||
namespace AntDesign.Internal
|
||||
{
|
||||
internal static class ColumnExpressionHelper
|
||||
{
|
||||
internal static MemberInfo GetReturnMemberInfo(LambdaExpression expression)
|
||||
{
|
||||
var accessorBody = expression.Body;
|
||||
|
||||
if (accessorBody is UnaryExpression unaryExpression
|
||||
&& unaryExpression.NodeType == ExpressionType.Convert
|
||||
&& unaryExpression.Type == typeof(object))
|
||||
{
|
||||
accessorBody = unaryExpression.Operand;
|
||||
}
|
||||
|
||||
if (accessorBody is ConditionalExpression conditionalExpression)
|
||||
{
|
||||
accessorBody = conditionalExpression.IfTrue;
|
||||
}
|
||||
|
||||
if (!(accessorBody is MemberExpression memberExpression))
|
||||
{
|
||||
throw new ArgumentException($"The type of the provided expression {accessorBody.GetType().Name} is not supported, it should be {nameof(MemberExpression)}.");
|
||||
}
|
||||
|
||||
return memberExpression.Member;
|
||||
}
|
||||
}
|
||||
}
|
@ -147,6 +147,7 @@ RenderFragment<(Table<TItem> table, IEnumerable<TItem> showItems, int level)> bo
|
||||
var table = context.table;
|
||||
var showItems = context.showItems;
|
||||
var level = context.level;
|
||||
var count = Math.Min(showItems.Count(), table._dataSourceCount);
|
||||
}
|
||||
|
||||
@if (table._total <= 0)
|
||||
@ -159,7 +160,7 @@ RenderFragment<(Table<TItem> table, IEnumerable<TItem> showItems, int level)> bo
|
||||
}
|
||||
else if (showItems != null && table.ColumnContext.Columns.Count > 0)
|
||||
{
|
||||
for (int i = 0; i < showItems.Count(); i++)
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
var rowIndex = table.PageSize * (table.PageIndex - 1) + i + 1;
|
||||
var data = showItems.ElementAt(i);
|
||||
@ -183,7 +184,7 @@ RenderFragment<(Table<TItem> table, IEnumerable<TItem> showItems, int level)> bo
|
||||
|
||||
<tr @attributes="rowAttributes"
|
||||
data-row-key="@(rowIndex-1)" class="ant-table-row ant-table-row-level-@level @(currentRowData.Selected ? "ant-table-row-selected" : "") @table.RowClassName(currentRowData) @rowAttributes?.GetValueOrDefault("class")">
|
||||
<CascadingValue Value="currentRowData" Name="RowData" IsFixed>
|
||||
<CascadingValue Value="currentRowData" Name="RowData" IsFixed="false">
|
||||
<CascadingValue Value="true" Name="IsBody" IsFixed>
|
||||
@table.ChildContent(data)
|
||||
</CascadingValue>
|
||||
@ -193,7 +194,7 @@ RenderFragment<(Table<TItem> table, IEnumerable<TItem> showItems, int level)> bo
|
||||
{
|
||||
@table.body((table, table.TreeChildren(data), level + 1));
|
||||
}
|
||||
@if (!hasChildren && table.ExpandTemplate != null && table.RowExpandable(currentRowData))
|
||||
@if (!hasChildren && table.ExpandTemplate != null && table.RowExpandable(currentRowData) && currentRowData.Expanded)
|
||||
{
|
||||
<tr class="ant-table-expanded-row ant-table-expanded-row-level-1 @table.ExpandedRowClassName(currentRowData)"
|
||||
style="@(currentRowData.Expanded?"":"display: none;")">
|
||||
|
@ -148,7 +148,7 @@ namespace AntDesign
|
||||
string ITable.ScrollX => ScrollX;
|
||||
string ITable.ScrollY => ScrollY;
|
||||
int ITable.ScrollBarWidth => ScrollBarWidth;
|
||||
int ITable.ExpandIconColumnIndex => ExpandIconColumnIndex;
|
||||
int ITable.ExpandIconColumnIndex => ExpandIconColumnIndex + (_selection != null && _selection.ColIndex <= ExpandIconColumnIndex ? 1 : 0);
|
||||
int ITable.TreeExpandIconColumnIndex => _treeExpandIconColumnIndex;
|
||||
bool ITable.HasExpandTemplate => ExpandTemplate != null;
|
||||
|
||||
@ -269,9 +269,9 @@ namespace AntDesign
|
||||
_treeMode = TreeChildren != null && (_showItems?.Any(x => TreeChildren(x)?.Any() == true) == true);
|
||||
if (_treeMode)
|
||||
{
|
||||
_treeExpandIconColumnIndex = ExpandIconColumnIndex + (_selection != null ? 1 : 0);
|
||||
_treeExpandIconColumnIndex = ExpandIconColumnIndex + (_selection != null && _selection.ColIndex <= ExpandIconColumnIndex ? 1 : 0);
|
||||
}
|
||||
|
||||
_waitingReload = false;
|
||||
StateHasChanged();
|
||||
|
||||
return queryModel;
|
||||
@ -327,19 +327,6 @@ namespace AntDesign
|
||||
{
|
||||
base.OnAfterRender(firstRender);
|
||||
|
||||
if (_waitingReloadAndInvokeChange)
|
||||
{
|
||||
_waitingReloadAndInvokeChange = false;
|
||||
_waitingReload = false;
|
||||
|
||||
ReloadAndInvokeChange();
|
||||
}
|
||||
else if (_waitingReload)
|
||||
{
|
||||
_waitingReload = false;
|
||||
Reload();
|
||||
}
|
||||
|
||||
if (!firstRender)
|
||||
{
|
||||
this.FinishLoadPage();
|
||||
@ -384,7 +371,22 @@ namespace AntDesign
|
||||
}
|
||||
}
|
||||
|
||||
protected override bool ShouldRender() => this._shouldRender;
|
||||
protected override bool ShouldRender()
|
||||
{
|
||||
if (_waitingReloadAndInvokeChange)
|
||||
{
|
||||
_waitingReloadAndInvokeChange = false;
|
||||
_waitingReload = false;
|
||||
|
||||
ReloadAndInvokeChange();
|
||||
}
|
||||
else if (_waitingReload)
|
||||
{
|
||||
_waitingReload = false;
|
||||
Reload();
|
||||
}
|
||||
return this._shouldRender;
|
||||
}
|
||||
|
||||
void ITable.HasFixLeft() => _hasFixLeft = true;
|
||||
|
||||
@ -431,7 +433,11 @@ namespace AntDesign
|
||||
_pingRight = true;
|
||||
}
|
||||
|
||||
_shouldRender = beforePingLeft != _pingLeft || beforePingRight != _pingRight;
|
||||
if (beforePingLeft != _pingLeft || beforePingRight != _pingRight)
|
||||
{
|
||||
_shouldRender = true;
|
||||
}
|
||||
|
||||
if (!clear)
|
||||
{
|
||||
StateHasChanged();
|
||||
|
@ -1,63 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
|
||||
namespace AntDesign.TableModels
|
||||
{
|
||||
public class DataIndexSortModel<TField> : ITableSortModel, IComparer<TField>
|
||||
{
|
||||
private readonly LambdaExpression _propertySelect;
|
||||
|
||||
private readonly Func<TField, TField, int> _comparer;
|
||||
|
||||
public int Priority { get; }
|
||||
|
||||
public string FieldName { get; }
|
||||
|
||||
public string Sort => _sortDirection?.Name;
|
||||
|
||||
SortDirection ITableSortModel.SortDirection => _sortDirection;
|
||||
|
||||
private SortDirection _sortDirection;
|
||||
|
||||
public DataIndexSortModel(string dataIndex, LambdaExpression propertySelect, int priority, SortDirection sortDirection, Func<TField, TField, int> comparer)
|
||||
{
|
||||
this.FieldName = dataIndex;
|
||||
this._propertySelect = propertySelect;
|
||||
this._comparer = comparer;
|
||||
this.Priority = priority;
|
||||
this._sortDirection = sortDirection ?? SortDirection.None;
|
||||
}
|
||||
|
||||
void ITableSortModel.SetSortDirection(SortDirection sortDirection)
|
||||
{
|
||||
_sortDirection = sortDirection;
|
||||
}
|
||||
|
||||
IOrderedQueryable<TItem> ITableSortModel.SortList<TItem>(IQueryable<TItem> source)
|
||||
{
|
||||
if (_sortDirection == SortDirection.None)
|
||||
{
|
||||
return source as IOrderedQueryable<TItem>;
|
||||
}
|
||||
|
||||
var lambda = (Expression<Func<TItem, TField>>)_propertySelect;
|
||||
|
||||
if (_sortDirection == SortDirection.Ascending)
|
||||
{
|
||||
return _comparer == null ? source.OrderBy(lambda) : source.OrderBy(lambda, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
return _comparer == null ? source.OrderByDescending(lambda) : source.OrderByDescending(lambda, this);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public int Compare(TField x, TField y)
|
||||
{
|
||||
return _comparer?.Invoke(x, y) ?? 0;
|
||||
}
|
||||
}
|
||||
}
|
@ -2,7 +2,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
|
||||
namespace AntDesign.TableModels
|
||||
{
|
||||
@ -16,12 +15,12 @@ namespace AntDesign.TableModels
|
||||
|
||||
public Expression<Func<TField, TField, bool>> OnFilter { get; set; }
|
||||
|
||||
private PropertyInfo _propertyInfo;
|
||||
public LambdaExpression GetFieldExpression { get; set; }
|
||||
|
||||
public FilterModel(PropertyInfo propertyInfo, Expression<Func<TField, TField, bool>> onFilter, IList<TableFilter<TField>> filters)
|
||||
public FilterModel(LambdaExpression getFieldExpression, Expression<Func<TField, TField, bool>> onFilter, IList<TableFilter<TField>> filters)
|
||||
{
|
||||
this._propertyInfo = propertyInfo;
|
||||
this.FieldName = _propertyInfo.Name;
|
||||
this.GetFieldExpression = getFieldExpression;
|
||||
this.FieldName = GetFieldExpression.ReturnType.Name;
|
||||
this.OnFilter = onFilter;
|
||||
this.SelectedValues = filters.Select(x => x.Value.ToString());
|
||||
this.Filters = filters;
|
||||
@ -34,14 +33,13 @@ namespace AntDesign.TableModels
|
||||
return source;
|
||||
}
|
||||
|
||||
var sourceExpression = Expression.Parameter(typeof(TItem));
|
||||
var propertyExpression = Expression.Property(sourceExpression, _propertyInfo);
|
||||
var sourceExpression = GetFieldExpression.Parameters[0];
|
||||
|
||||
Expression invocationExpression = Expression.Invoke((Expression<Func<bool>>)(() => false));
|
||||
Expression invocationExpression = Expression.Constant(false, typeof(bool));
|
||||
|
||||
foreach (var filter in Filters)
|
||||
{
|
||||
invocationExpression = Expression.OrElse(invocationExpression, Expression.Invoke(OnFilter, Expression.Constant(filter.Value), propertyExpression));
|
||||
invocationExpression = Expression.OrElse(invocationExpression, Expression.Invoke(OnFilter, Expression.Constant(filter.Value), GetFieldExpression.Body));
|
||||
}
|
||||
|
||||
var lambda = Expression.Lambda<Func<TItem, bool>>(invocationExpression, sourceExpression);
|
||||
|
@ -1,8 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using AntDesign.Internal;
|
||||
|
||||
namespace AntDesign.TableModels
|
||||
{
|
||||
@ -16,16 +18,18 @@ namespace AntDesign.TableModels
|
||||
|
||||
SortDirection ITableSortModel.SortDirection => _sortDirection;
|
||||
|
||||
private readonly PropertyInfo _propertyInfo;
|
||||
private readonly Func<TField, TField, int> _comparer;
|
||||
|
||||
private SortDirection _sortDirection;
|
||||
|
||||
public SortModel(PropertyInfo propertyInfo, int priority, SortDirection defaultSortOrder, Func<TField, TField, int> comparer)
|
||||
private LambdaExpression _getFieldExpression;
|
||||
|
||||
public SortModel(LambdaExpression getFieldExpression, int priority, SortDirection defaultSortOrder, Func<TField, TField, int> comparer)
|
||||
{
|
||||
this.Priority = priority;
|
||||
this.FieldName = propertyInfo?.Name;
|
||||
this._propertyInfo = propertyInfo;
|
||||
this._getFieldExpression = getFieldExpression;
|
||||
var member = ColumnExpressionHelper.GetReturnMemberInfo(_getFieldExpression);
|
||||
this.FieldName = member.GetCustomAttribute<DisplayAttribute>(true)?.Name ?? member.Name;
|
||||
this._comparer = comparer;
|
||||
this._sortDirection = defaultSortOrder ?? SortDirection.None;
|
||||
}
|
||||
@ -42,11 +46,7 @@ namespace AntDesign.TableModels
|
||||
return source as IOrderedQueryable<TItem>;
|
||||
}
|
||||
|
||||
var sourceExpression = Expression.Parameter(typeof(TItem));
|
||||
|
||||
var propertyExpression = Expression.Property(sourceExpression, _propertyInfo);
|
||||
|
||||
var lambda = Expression.Lambda<Func<TItem, TField>>(propertyExpression, sourceExpression);
|
||||
var lambda = (Expression<Func<TItem, TField>>)_getFieldExpression;
|
||||
|
||||
if (_sortDirection == SortDirection.Ascending)
|
||||
{
|
||||
|
@ -123,11 +123,14 @@
|
||||
{
|
||||
<a target="_blank" rel="noopener noreferrer" class="ant-upload-list-item-name" title="@file.FileName" href="@file.Url">@file.FileName</a>
|
||||
}
|
||||
<span class="ant-upload-list-item-card-actions @picture">
|
||||
<button title="@Locale.RemoveFile" type="button" class="ant-btn ant-btn-text ant-btn-sm ant-btn-icon-only ant-upload-list-item-card-actions-btn" @onclick="() => RemoveFile(file)" disabled="@Disabled">
|
||||
<Icon Type="delete" />
|
||||
</button>
|
||||
</span>
|
||||
@if (!IsPictureCard)
|
||||
{
|
||||
<span class="ant-upload-list-item-card-actions @picture">
|
||||
<button title="@Locale.RemoveFile" type="button" class="ant-btn ant-btn-text ant-btn-sm ant-btn-icon-only ant-upload-list-item-card-actions-btn" @onclick="() => RemoveFile(file)" disabled="@Disabled">
|
||||
<Icon Type="delete" />
|
||||
</button>
|
||||
</span>
|
||||
}
|
||||
</span>
|
||||
</div>
|
||||
@if (IsPictureCard)
|
||||
|
@ -150,6 +150,7 @@ namespace AntDesign.Internal
|
||||
public async Task UploadSuccess(string id, string returnData)
|
||||
{
|
||||
var file = Upload.FileList.FirstOrDefault(x => x.Id.Equals(id));
|
||||
_uploadInfo.FileList = Upload.FileList;
|
||||
if (file == null)
|
||||
{
|
||||
return;
|
||||
@ -182,6 +183,7 @@ namespace AntDesign.Internal
|
||||
file.State = UploadState.Fail;
|
||||
file.Percent = 100;
|
||||
_uploadInfo.File = file;
|
||||
_uploadInfo.FileList = Upload.FileList;
|
||||
file.Response ??= reponseCode;
|
||||
await UploadChanged(id, 100);
|
||||
await InvokeAsync(StateHasChanged);
|
||||
@ -205,6 +207,7 @@ namespace AntDesign.Internal
|
||||
}
|
||||
file.Percent = progress;
|
||||
_uploadInfo.File = file;
|
||||
_uploadInfo.FileList = Upload.FileList;
|
||||
await InvokeAsync(StateHasChanged);
|
||||
if (Upload.OnChange.HasDelegate)
|
||||
{
|
||||
|
@ -49,7 +49,7 @@ namespace AntDesign.Docs.Build.CLI.Command
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(ex.Message);
|
||||
Console.WriteLine(ex.StackTrace);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -8,13 +8,8 @@
|
||||
<ProjectReference Include="..\AntDesign.Docs\AntDesign.Docs.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<DocFiles Include="$(SolutionDir)docs\**\*.*"></DocFiles>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Watch Include="$(SolutionDir)**\*.razor" />
|
||||
</ItemGroup>
|
||||
<Target Name="CopyDocs" BeforeTargets="Build">
|
||||
<Copy SourceFiles="@(DocFiles)" DestinationFolder="$(ProjectDir)\wwwroot\docs\%(RecursiveDir)" ContinueOnError="true" />
|
||||
</Target>
|
||||
|
||||
</Project>
|
@ -17,7 +17,7 @@
|
||||
</head>
|
||||
<body>
|
||||
<app>
|
||||
<component type="typeof(App)" render-mode="Server" />
|
||||
<component type="typeof(App)" render-mode="ServerPrerendered" />
|
||||
</app>
|
||||
|
||||
<script src="_content/AntDesign.Charts/g2plot.js"></script>
|
||||
@ -38,4 +38,4 @@
|
||||
<script src="https://cdn.jsdelivr.net/npm/docsearch.js@2.6.3/dist/cdn/docsearch.min.js" integrity="sha256-qybEsgf0PGiQS22AmoozPs09oRnSC7Gu7eBu4fbS2Ac=" crossorigin="anonymous"></script>
|
||||
<script src="_content/AntDesign.Docs/js/docsearch.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
@ -25,11 +25,4 @@
|
||||
<Content Include="$(SolutionDir)scripts\gh-pages\**" LinkBase="gh-pages" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<DocFiles Include="$(SolutionDir)docs\**\*.*" />
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="CopyDocs" BeforeTargets="Build">
|
||||
<Copy SourceFiles="@(DocFiles)" DestinationFolder="$(ProjectDir)\wwwroot\docs\%(RecursiveDir)" ContinueOnError="true" />
|
||||
</Target>
|
||||
</Project>
|
@ -50,11 +50,17 @@
|
||||
<ProjectDir>$(SolutionDir)/site/AntDesign.Docs</ProjectDir>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<DocFiles Include="$(SolutionDir)docs\**\*.*" />
|
||||
<DocFiles Include="$(SolutionDir)\CHANGELOG.*.*" />
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="RunCli" BeforeTargets="Build" Condition=" '$(Configuration)' == 'Debug'">
|
||||
<Copy SourceFiles="@(DocFiles)" DestinationFolder="$(ProjectDir)\wwwroot\docs\%(RecursiveDir)" ContinueOnError="true" />
|
||||
<Exec WorkingDirectory="$(SolutionDir)" Command="dotnet build $(CLIProjectDir)" />
|
||||
<Exec WorkingDirectory="$(SolutionDir)" Command="dotnet $(CLIPath) demo2json $(ProjectDir)/Demos $(ProjectDir)/wwwroot/meta" />
|
||||
<Exec WorkingDirectory="$(SolutionDir)" Command="dotnet $(CLIPath) menu2json $(ProjectDir)/Demos docs $(ProjectDir)/wwwroot/meta" />
|
||||
<Exec WorkingDirectory="$(SolutionDir)" Command="dotnet $(CLIPath) docs2html ./docs ./site/AntDesign.Docs/wwwroot/docs" />
|
||||
<Exec WorkingDirectory="$(SolutionDir)" Command="dotnet $(CLIPath) menu2json $(ProjectDir)/Demos $(ProjectDir)/wwwroot/docs $(ProjectDir)/wwwroot/meta" />
|
||||
<Exec WorkingDirectory="$(SolutionDir)" Command="dotnet $(CLIPath) docs2html $(ProjectDir)/wwwroot/docs ./site/AntDesign.Docs/wwwroot/docs" />
|
||||
</Target>
|
||||
|
||||
<Target Name="PublishRunGulp" AfterTargets="ComputeFilesToPublish">
|
||||
|
@ -0,0 +1,26 @@
|
||||
@using System.ComponentModel.DataAnnotations;
|
||||
|
||||
<Form Model="@model"
|
||||
LabelColSpan="8"
|
||||
WrapperColSpan="16">
|
||||
<FormItem>
|
||||
<LabelTemplate>
|
||||
<label class="ant-form-item-required" for="username">
|
||||
<Tooltip Title="@("Enter your username")">Username</Tooltip>
|
||||
</label>
|
||||
</LabelTemplate>
|
||||
<ChildContent>
|
||||
<Input Id="username" @bind-Value="@context.Username" />
|
||||
</ChildContent>
|
||||
</FormItem>
|
||||
</Form>
|
||||
|
||||
@code{
|
||||
public class Model
|
||||
{
|
||||
[Required]
|
||||
public string Username { get; set; }
|
||||
}
|
||||
|
||||
private Model model = new Model();
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
order: 6
|
||||
title:
|
||||
zh-CN: 复杂一点的控件
|
||||
en-US: complex form control
|
||||
en-US: Complex form control
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
@ -0,0 +1,14 @@
|
||||
---
|
||||
order: 6.2
|
||||
title:
|
||||
zh-CN: 自定义标签
|
||||
en-US: Customized Label
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
标签可以通过LabelTemplate来自定义。
|
||||
|
||||
## en-US
|
||||
|
||||
Label can be customized by using LabelTemplate.
|
@ -1,48 +0,0 @@
|
||||
<div>
|
||||
<Divider Orientation="left" Style="color: #333; font-weight:normal">
|
||||
Align Top
|
||||
</Divider>
|
||||
|
||||
<div class="flex-demo">
|
||||
<Row Justify="center" Align="top">
|
||||
<Col Span="4"><p class="height-100">col-4</p></Col>
|
||||
<Col Span="4"><p class="height-50">col-4</p></Col>
|
||||
<Col Span="4"><p class="height-120">col-4</p></Col>
|
||||
<Col Span="4"><p class="height-80">col-4</p></Col>
|
||||
</Row>
|
||||
</div>
|
||||
|
||||
|
||||
<Divider Orientation="left" Style="color: #333; font-weight:normal">
|
||||
Align Center
|
||||
</Divider>
|
||||
<div class="flex-demo">
|
||||
<Row Justify="space-around" Align="middle">
|
||||
<Col Span="4"><p class="height-100">col-4</p></Col>
|
||||
<Col Span="4"><p class="height-50">col-4</p></Col>
|
||||
<Col Span="4"><p class="height-120">col-4</p></Col>
|
||||
<Col Span="4"><p class="height-80">col-4</p></Col>
|
||||
</Row>
|
||||
</div>
|
||||
|
||||
<Divider Orientation="left" Style="color: #333; font-weight:normal">
|
||||
Align Bottom
|
||||
</Divider>
|
||||
<div class="flex-demo">
|
||||
<Row Justify="space-between" Align="bottom">
|
||||
<Col Span="4"><p class="height-100">col-4</p></Col>
|
||||
<Col Span="4"><p class="height-50">col-4</p></Col>
|
||||
<Col Span="4"><p class="height-120">col-4</p></Col>
|
||||
<Col Span="4"><p class="height-80">col-4</p></Col>
|
||||
</Row>
|
||||
</div>
|
||||
</div>
|
||||
<style>
|
||||
.flex-demo {
|
||||
background-color: rgba(128, 128, 128, 0.08);
|
||||
}
|
||||
</style>
|
||||
|
||||
@code{
|
||||
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
---
|
||||
order: 11
|
||||
title:
|
||||
zh-CN: useBreakpoint Hook
|
||||
en-US: useBreakpoint Hook
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
使用 useBreakpoint Hook 个性化布局。
|
||||
|
||||
## en-US
|
||||
|
||||
Use useBreakpoint Hook provide personalized layout.
|
@ -1,21 +0,0 @@
|
||||
<div>
|
||||
<Text> Current break point:</Text>
|
||||
<Tag Color="blue">
|
||||
sm
|
||||
</Tag>
|
||||
<Tag Color="blue">
|
||||
md
|
||||
</Tag>
|
||||
<Tag Color="blue">
|
||||
lg
|
||||
</Tag>
|
||||
<Tag Color="blue">
|
||||
xl
|
||||
</Tag>
|
||||
<Tag Color="blue">
|
||||
xxl
|
||||
</Tag>
|
||||
</div>
|
||||
@code{
|
||||
|
||||
}
|
49
site/AntDesign.Docs/Demos/Components/Grid/demo/Flex.razor
Normal file
49
site/AntDesign.Docs/Demos/Components/Grid/demo/Flex.razor
Normal file
@ -0,0 +1,49 @@
|
||||
<div>
|
||||
<Divider Orientation="left">sub-element align left</Divider>
|
||||
<Row Justify="start">
|
||||
<Col Span="4">col-4</Col>
|
||||
<Col Span="4">col-4</Col>
|
||||
<Col Span="4">col-4</Col>
|
||||
<Col Span="4">col-4</Col>
|
||||
</Row>
|
||||
|
||||
<Divider Orientation="left">sub-element align center</Divider>
|
||||
<Row Justify="center">
|
||||
<Col Span="4">col-4</Col>
|
||||
<Col Span="4">col-4</Col>
|
||||
<Col Span="4">col-4</Col>
|
||||
<Col Span="4">col-4</Col>
|
||||
</Row>
|
||||
|
||||
<Divider Orientation="left">sub-element align right</Divider>
|
||||
<Row Justify="end">
|
||||
<Col Span="4">col-4</Col>
|
||||
<Col Span="4">col-4</Col>
|
||||
<Col Span="4">col-4</Col>
|
||||
<Col Span="4">col-4</Col>
|
||||
</Row>
|
||||
|
||||
|
||||
<Divider Orientation="left">sub-element monospaced arrangement</Divider>
|
||||
<Row Justify="space-between">
|
||||
<Col Span="4">col-4</Col>
|
||||
<Col Span="4">col-4</Col>
|
||||
<Col Span="4">col-4</Col>
|
||||
<Col Span="4">col-4</Col>
|
||||
</Row>
|
||||
|
||||
|
||||
<Divider Orientation="left">sub-element align full</Divider>
|
||||
<Row Justify="space-around">
|
||||
<Col Span="4">col-4</Col>
|
||||
<Col Span="4">col-4</Col>
|
||||
<Col Span="4">col-4</Col>
|
||||
<Col Span="4">col-4</Col>
|
||||
</Row>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
#components-grid-demo-flex [class~='ant-row'] {
|
||||
background: rgba(128, 128, 128, 0.08);
|
||||
}
|
||||
</style>
|
@ -0,0 +1,59 @@
|
||||
<div>
|
||||
<Divider Orientation="left">Align Top</Divider>
|
||||
<Row Justify="center" Align="top">
|
||||
<Col Span="4">
|
||||
@DemoBox((100, "col-4"))
|
||||
</Col>
|
||||
<Col Span="4">
|
||||
@DemoBox((50, "col-4"))
|
||||
</Col>
|
||||
<Col Span="4">
|
||||
@DemoBox((120, "col-4"))
|
||||
</Col>
|
||||
<Col Span="4">
|
||||
@DemoBox((80, "col-4"))
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Divider Orientation="left">Align Middle</Divider>
|
||||
<Row Justify="space-around" Align="middle">
|
||||
<Col Span="4">
|
||||
@DemoBox((100, "col-4"))
|
||||
</Col>
|
||||
<Col Span="4">
|
||||
@DemoBox((50, "col-4"))
|
||||
</Col>
|
||||
<Col Span="4">
|
||||
@DemoBox((120, "col-4"))
|
||||
</Col>
|
||||
<Col Span="4">
|
||||
@DemoBox((80, "col-4"))
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<Divider Orientation="left">Align Bottom</Divider>
|
||||
<Row Justify="space-between" Align="bottom">
|
||||
<Col Span="4">
|
||||
@DemoBox((100, "col-4"))
|
||||
</Col>
|
||||
<Col Span="4">
|
||||
@DemoBox((50, "col-4"))
|
||||
</Col>
|
||||
<Col Span="4">
|
||||
@DemoBox((120, "col-4"))
|
||||
</Col>
|
||||
<Col Span="4">
|
||||
@DemoBox((80, "col-4"))
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
#components-grid-demo-flex-align [class~='ant-row'] {
|
||||
background: rgba(128, 128, 128, 0.08);
|
||||
}
|
||||
</style>
|
||||
|
||||
@code{
|
||||
RenderFragment<(int value, string children)> DemoBox = props =>@<p class="@($"height-{props.value}")">@props.children</p>;
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
<div>
|
||||
<Divider Orientation="left">Normal</Divider>
|
||||
<Row>
|
||||
<Col Span="6" Order="4">
|
||||
1 col-order-4
|
||||
</Col>
|
||||
<Col Span="6" Order="3">
|
||||
2 col-order-3
|
||||
</Col>
|
||||
<Col Span="6" Order="2">
|
||||
3 col-order-2
|
||||
</Col>
|
||||
<Col Span="6" Order="1">
|
||||
4 col-order-1
|
||||
</Col>
|
||||
</Row>
|
||||
<Divider Orientation="left">Responsive</Divider>
|
||||
<Row>
|
||||
<Col Span="6" Xs="new EmbeddedProperty{ Order= 1 }" Sm="new EmbeddedProperty{ Order= 2 }" Md="new EmbeddedProperty{ Order= 3 }" Lg="new EmbeddedProperty{ Order= 4 }">
|
||||
1 col-order-responsive
|
||||
</Col>
|
||||
<Col Span="6" Xs="new EmbeddedProperty{ Order= 2 }" Sm="new EmbeddedProperty{ Order= 1 }" Md="new EmbeddedProperty{ Order= 4 }" Lg="new EmbeddedProperty{ Order= 3 }" >
|
||||
2 col-order-responsive
|
||||
</Col>
|
||||
<Col Span="6" Xs="new EmbeddedProperty{ Order= 3 }" Sm="new EmbeddedProperty{ Order= 4 }" Md="new EmbeddedProperty{ Order= 2 }" Lg="new EmbeddedProperty{ Order= 1 }" >
|
||||
3 col-order-responsive
|
||||
</Col>
|
||||
<Col Span="6" Xs="new EmbeddedProperty{ Order= 4 }" Sm="new EmbeddedProperty{ Order= 3 }" Md="new EmbeddedProperty{ Order= 1 }" Lg="new EmbeddedProperty{ Order= 2 }" >
|
||||
4 col-order-responsive
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
#components-grid-demo-flex-order [class~='ant-row'] {
|
||||
background: rgba(128, 128, 128, 0.08);
|
||||
}
|
||||
</style>
|
@ -0,0 +1,24 @@
|
||||
<div>
|
||||
<Divider Orientation="left">Percentage columns</Divider>
|
||||
<Row>
|
||||
<Col Flex="2">2 / 5</Col>
|
||||
<Col Flex="3">3 / 5</Col>
|
||||
</Row>
|
||||
<Divider Orientation="left">Fill rest</Divider>
|
||||
<Row>
|
||||
<Col Flex=@("100px")>100px</Col>
|
||||
<Col Flex=@("auto")>Fill Rest</Col>
|
||||
</Row>
|
||||
<Divider Orientation="left">Raw flex style</Divider>
|
||||
<Row>
|
||||
<Col Flex=@("1 1 200px")>1 1 200px</Col>
|
||||
<Col Flex=@("0 1 300px")>0 1 300px</Col>
|
||||
</Row>
|
||||
|
||||
<Row Wrap="false">
|
||||
<Col Flex=@("none")>
|
||||
<div style="padding: 0 16px">none</div>
|
||||
</Col>
|
||||
<Col Flex=@("auto")>auto with no-wrap</Col>
|
||||
</Row>
|
||||
</div>
|
@ -1,85 +1,6 @@
|
||||
<div>
|
||||
<style>
|
||||
.Gutter-box {
|
||||
background: rgb(0, 146, 255);
|
||||
padding: 8px 0;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
<AntDesign.Divider Orientation="left" Style="color: #333; font-weight:normal">
|
||||
Horizontal
|
||||
</AntDesign.Divider>
|
||||
|
||||
<div class="Gutter-example">
|
||||
<AntDesign.Row Gutter="16">
|
||||
<AntDesign.Col class="gutter-row" Span="6">
|
||||
<div class="Gutter-box">col-6</div>
|
||||
</AntDesign.Col>
|
||||
<AntDesign.Col class="gutter-row" Span="6">
|
||||
<div class="Gutter-box">col-6</div>
|
||||
</AntDesign.Col>
|
||||
<AntDesign.Col class="gutter-row" Span="6">
|
||||
<div class="Gutter-box">col-6</div>
|
||||
</AntDesign.Col>
|
||||
<AntDesign.Col class="gutter-row" Span="6">
|
||||
<div class="Gutter-box">col-6</div>
|
||||
</AntDesign.Col>
|
||||
</AntDesign.Row>
|
||||
</div>
|
||||
<Divider Orientation="left" Style="color: #333; font-weight:normal">
|
||||
Responsive
|
||||
</Divider>
|
||||
<div class="Gutter-example">
|
||||
<AntDesign.Row Gutter="@Gutter1">
|
||||
<AntDesign.Col class="gutter-row" Span="6">
|
||||
<div class="Gutter-box">col-6</div>
|
||||
</AntDesign.Col>
|
||||
<AntDesign.Col class="gutter-row" Span="6">
|
||||
<div class="Gutter-box">col-6</div>
|
||||
</AntDesign.Col>
|
||||
<AntDesign.Col class="gutter-row" Span="6">
|
||||
<div class="Gutter-box">col-6</div>
|
||||
</AntDesign.Col>
|
||||
<AntDesign.Col class="gutter-row" Span="6">
|
||||
<div class="Gutter-box">col-6</div>
|
||||
</AntDesign.Col>
|
||||
</AntDesign.Row>
|
||||
</div>
|
||||
<Divider Orientation="left" Style="color: #333; font-weight:normal">
|
||||
Vertical
|
||||
</Divider>
|
||||
<div class="Gutter-example">
|
||||
<AntDesign.Row Gutter="(16,24)">
|
||||
<AntDesign.Col class="gutter-row" Span="6">
|
||||
<div class="Gutter-box">col-6</div>
|
||||
</AntDesign.Col>
|
||||
<AntDesign.Col class="gutter-row" Span="6">
|
||||
<div class="Gutter-box">col-6</div>
|
||||
</AntDesign.Col>
|
||||
<AntDesign.Col class="gutter-row" Span="6">
|
||||
<div class="Gutter-box">col-6</div>
|
||||
</AntDesign.Col>
|
||||
<AntDesign.Col class="gutter-row" Span="6">
|
||||
<div class="Gutter-box">col-6</div>
|
||||
</AntDesign.Col>
|
||||
<AntDesign.Col class="gutter-row" Span="6">
|
||||
<div class="Gutter-box">col-6</div>
|
||||
</AntDesign.Col>
|
||||
<AntDesign.Col class="gutter-row" Span="6">
|
||||
<div class="Gutter-box">col-6</div>
|
||||
</AntDesign.Col>
|
||||
<AntDesign.Col class="gutter-row" Span="6">
|
||||
<div class="Gutter-box">col-6</div>
|
||||
</AntDesign.Col>
|
||||
<AntDesign.Col class="gutter-row" Span="6">
|
||||
<div class="Gutter-box">col-6</div>
|
||||
</AntDesign.Col>
|
||||
</AntDesign.Row>
|
||||
</div>
|
||||
</div>
|
||||
@code{
|
||||
Dictionary<string, int> Gutter1 = new Dictionary<string, int>()
|
||||
@{
|
||||
string style="background: #0092ff; padding: 8px 0;";
|
||||
Dictionary<string, int> gutter = new()
|
||||
{
|
||||
["xs"] = 8,
|
||||
["sm"] = 16,
|
||||
@ -88,6 +9,71 @@
|
||||
["xl"] = 48,
|
||||
["xxl"] = 64
|
||||
};
|
||||
|
||||
}
|
||||
<div>
|
||||
<Divider Orientation="left">Horizontal</Divider>
|
||||
<Row Gutter="16">
|
||||
<AntDesign.Col Class="gutter-row" Span="6">
|
||||
<div style="@style">col-6</div>
|
||||
</AntDesign.Col>
|
||||
<AntDesign.Col Class="gutter-row" Span="6">
|
||||
<div style="@style">col-6</div>
|
||||
</AntDesign.Col>
|
||||
<AntDesign.Col Class="gutter-row" Span="6">
|
||||
<div style="@style">col-6</div>
|
||||
</AntDesign.Col>
|
||||
<AntDesign.Col Class="gutter-row" Span="6">
|
||||
<div style="@style">col-6</div>
|
||||
</AntDesign.Col>
|
||||
</Row>
|
||||
<Divider Orientation="left">Responsive</Divider>
|
||||
<Row Gutter="@gutter">
|
||||
<AntDesign.Col Class="gutter-row" Span="6">
|
||||
<div style="@style">col-6</div>
|
||||
</AntDesign.Col>
|
||||
<AntDesign.Col Class="gutter-row" Span="6">
|
||||
<div style="@style">col-6</div>
|
||||
</AntDesign.Col>
|
||||
<AntDesign.Col Class="gutter-row" Span="6">
|
||||
<div style="@style">col-6</div>
|
||||
</AntDesign.Col>
|
||||
<AntDesign.Col Class="gutter-row" Span="6">
|
||||
<div style="@style">col-6</div>
|
||||
</AntDesign.Col>
|
||||
</Row>
|
||||
<Divider Orientation="left">Vertical</Divider>
|
||||
<Row Gutter="(16,24)">
|
||||
<AntDesign.Col Class="gutter-row" Span="6">
|
||||
<div style="@style">col-6</div>
|
||||
</AntDesign.Col>
|
||||
<AntDesign.Col Class="gutter-row" Span="6">
|
||||
<div style="@style">col-6</div>
|
||||
</AntDesign.Col>
|
||||
<AntDesign.Col Class="gutter-row" Span="6">
|
||||
<div style="@style">col-6</div>
|
||||
</AntDesign.Col>
|
||||
<AntDesign.Col Class="gutter-row" Span="6">
|
||||
<div style="@style">col-6</div>
|
||||
</AntDesign.Col>
|
||||
<AntDesign.Col Class="gutter-row" Span="6">
|
||||
<div style="@style">col-6</div>
|
||||
</AntDesign.Col>
|
||||
<AntDesign.Col Class="gutter-row" Span="6">
|
||||
<div style="@style">col-6</div>
|
||||
</AntDesign.Col>
|
||||
<AntDesign.Col Class="gutter-row" Span="6">
|
||||
<div style="@style">col-6</div>
|
||||
</AntDesign.Col>
|
||||
<AntDesign.Col Class="gutter-row" Span="6">
|
||||
<div style="@style">col-6</div>
|
||||
</AntDesign.Col>
|
||||
</Row>
|
||||
|
||||
}
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.gutter-box {
|
||||
padding: 8px 0;
|
||||
background: #00a0e9;
|
||||
}
|
||||
</style>
|
||||
|
@ -1,15 +0,0 @@
|
||||
---
|
||||
order: 9
|
||||
title:
|
||||
zh-CN: 其他属性的响应式
|
||||
en-US: More responsive
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
span pull push offset order 属性可以通过内嵌到 xs sm md lg xl xxl 属性中来使用。
|
||||
其中 xs={6} 相当于 xs={{ span: 6 }}。
|
||||
|
||||
## en-US
|
||||
|
||||
span pull push offset order property can be embedded into xs sm md lg xl properties to use, where xs={6} is equivalent to xs={{span: 6}}.
|
@ -1,40 +0,0 @@
|
||||
<div>
|
||||
<Row>
|
||||
<Col Xs="@xs1" Lg="lg1">
|
||||
Col
|
||||
</Col>
|
||||
<Col Xs="@xs2" Lg="lg1">
|
||||
Col
|
||||
</Col>
|
||||
<Col Xs="@xs3" Lg="lg1">
|
||||
Col
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
|
||||
@code
|
||||
{
|
||||
EmbeddedProperty xs1 = new EmbeddedProperty()
|
||||
{
|
||||
Span="5",
|
||||
Offset="1"
|
||||
};
|
||||
|
||||
EmbeddedProperty lg1 = new EmbeddedProperty()
|
||||
{
|
||||
Span = "6",
|
||||
Offset = "2"
|
||||
};
|
||||
|
||||
EmbeddedProperty xs2 = new EmbeddedProperty()
|
||||
{
|
||||
Span = "11",
|
||||
Offset = "1"
|
||||
};
|
||||
|
||||
EmbeddedProperty xs3= new EmbeddedProperty()
|
||||
{
|
||||
Span = "5",
|
||||
Offset = "1"
|
||||
};
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
---
|
||||
order: 2
|
||||
title:
|
||||
zh-CN: 栅格排序
|
||||
en-US: Column offset
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
列排序。
|
||||
通过使用 `push` 和 `pull` 类就可以很容易的改变列(column)的顺序。
|
||||
|
||||
## en-US
|
||||
|
||||
`Offset` can set the column to the right side. For example, using `offset = {4}` can set the element shifted to the right four columns width.
|
@ -1,14 +0,0 @@
|
||||
---
|
||||
order: 6
|
||||
title:
|
||||
zh-CN: 排序
|
||||
en-US: Order
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
通过 Order 来改变元素的排序。
|
||||
|
||||
## en-US
|
||||
|
||||
To change the element sort by order.
|
@ -1,29 +0,0 @@
|
||||
|
||||
<div id="grid-demo-flex-Order">
|
||||
<Row>
|
||||
<Col Span="6" Order="4">
|
||||
1 col-Order-4
|
||||
</Col>
|
||||
<Col Span="6" Order="3">
|
||||
2 col-Order-3
|
||||
</Col>
|
||||
<Col Span="6" Order="2">
|
||||
3 col-Order-2
|
||||
</Col>
|
||||
<Col Span="6" Order="1">
|
||||
4 col-Order-1
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<style>
|
||||
#grid-demo-flex-Order .ant-row {
|
||||
background-color: rgba(128, 128, 128, 0.08);
|
||||
}
|
||||
</style>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
@code{
|
||||
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
---
|
||||
order: 10
|
||||
title:
|
||||
zh-CN: 栅格配置器
|
||||
en-US: Playground
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
可以简单配置几种等分栅格和间距。
|
||||
|
||||
## en-US
|
||||
|
||||
A simple playground for column count and gutter.
|
@ -1,14 +0,0 @@
|
||||
---
|
||||
order: 8
|
||||
title:
|
||||
zh-CN: 响应式布局
|
||||
en-US: Responsive
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
参照 Bootstrap 的 响应式设计,预设六个响应尺寸:xs sm md lg xl xxl。
|
||||
|
||||
## en-US
|
||||
|
||||
Referring to the Bootstrap responsive design, here preset six dimensions: xs sm md lg xl.
|
@ -1,13 +1,12 @@
|
||||
<div>
|
||||
<Row>
|
||||
<Col Xs="2" Sm="4" Md="6" Lg="8" Xl="10">
|
||||
Col
|
||||
</Col>
|
||||
<Col Xs="20" Sm="16" Md="12" Lg="8" Xl="4">
|
||||
Col
|
||||
</Col>
|
||||
<Col Xs="2" Sm="4" Md="6" Lg="8" Xl="10">
|
||||
Col
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
<Row>
|
||||
<Col Xs="2" Sm="4" Md="6" Lg="8" Xl="10">
|
||||
Col
|
||||
</Col>
|
||||
<Col Xs="20" Sm="16" Md="12" Lg="8" Xl="4">
|
||||
Col
|
||||
</Col>
|
||||
<Col Xs="2" Sm="4" Md="6" Lg="8" Xl="10">
|
||||
Col
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
|
@ -0,0 +1,13 @@
|
||||
<Row>
|
||||
<Col Xs="@Property(5,1)" Lg="@Property(6,2)">
|
||||
Col
|
||||
</Col>
|
||||
<Col Xs="@Property(11,1)" Lg="@Property(6,2)">
|
||||
Col
|
||||
</Col>
|
||||
<Col Xs="@Property(5,1)" Lg="@Property(6,2)">
|
||||
Col
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
@code{ EmbeddedProperty Property(int span, int offset) => new() { Span = span, Offset = offset }; }
|
@ -1,15 +0,0 @@
|
||||
---
|
||||
order: 4
|
||||
title:
|
||||
zh-CN: 排版
|
||||
en-US: Typesetting
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
布局基础。
|
||||
子元素根据不同的值 start,center,end,space-between,space-around,分别定义其在父节点里面的排版方式。
|
||||
|
||||
## en-US
|
||||
|
||||
Child elements depending on the value of the start,center, end,space-between, space-around, which are defined in its parent node typesetting mode.
|
@ -1,49 +0,0 @@
|
||||
<div>
|
||||
<div id="flex-demo">
|
||||
<p>sub-element Align left</p>
|
||||
<Row Justify="start">
|
||||
<Col Span="4">col-4</Col>
|
||||
<Col Span="4">col-4</Col>
|
||||
<Col Span="4">col-4</Col>
|
||||
<Col Span="4">col-4</Col>
|
||||
</Row>
|
||||
<p>sub-element Align center</p>
|
||||
<Row Justify="center">
|
||||
<Col Span="4">col-4</Col>
|
||||
<Col Span="4">col-4</Col>
|
||||
<Col Span="4">col-4</Col>
|
||||
<Col Span="4">col-4</Col>
|
||||
</Row>
|
||||
<p>sub-element Align right</p>
|
||||
<Row Justify="end">
|
||||
<Col Span="4">col-4</Col>
|
||||
<Col Span="4">col-4</Col>
|
||||
<Col Span="4">col-4</Col>
|
||||
<Col Span="4">col-4</Col>
|
||||
</Row>
|
||||
<p>sub-element monospaced arrangement</p>
|
||||
<Row Justify="space-between">
|
||||
<Col Span="4">col-4</Col>
|
||||
<Col Span="4">col-4</Col>
|
||||
<Col Span="4">col-4</Col>
|
||||
<Col Span="4">col-4</Col>
|
||||
</Row>
|
||||
<p>sub-element Align full</p>
|
||||
<Row Justify="space-around">
|
||||
<Col Span="4">col-4</Col>
|
||||
<Col Span="4">col-4</Col>
|
||||
<Col Span="4">col-4</Col>
|
||||
<Col Span="4">col-4</Col>
|
||||
</Row>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
#flex-demo .ant-row {
|
||||
background-color: rgba(128, 128, 128, 0.08);
|
||||
}
|
||||
</style>
|
||||
|
||||
</div>
|
||||
@code{
|
||||
|
||||
}
|
@ -1,13 +1,10 @@
|
||||
<div>
|
||||
<Row>
|
||||
<Col Span="18" Push="6">
|
||||
col-18 col-Push-6
|
||||
col-18 col-push-6
|
||||
</Col>
|
||||
<Col Span="6" Pull="18">
|
||||
col-6 col-Pull-18
|
||||
col-6 col-pull-18
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
@code{
|
||||
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
---
|
||||
order: 7
|
||||
title:
|
||||
zh-CN: Flex 填充
|
||||
en-US: Flex Stretch
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
Col 提供 flex 属性以支持填充。
|
||||
|
||||
## en-US
|
||||
|
||||
Col provides flex prop to support fill rest.
|
@ -1,19 +0,0 @@
|
||||
<div>
|
||||
<Divider Orientation="left" Style="color: #333; font-weight:normal">
|
||||
Percentage columns
|
||||
</Divider>
|
||||
<p>To do</p>
|
||||
<Divider Orientation="left" Style="color: #333; font-weight:normal">
|
||||
Fill rest
|
||||
</Divider>
|
||||
<p>To do</p>
|
||||
<Divider Orientation="left" Style="color: #333; font-weight:normal">
|
||||
Raw flex style
|
||||
</Divider>
|
||||
<p>To do</p>
|
||||
</div>
|
||||
|
||||
|
||||
@code{
|
||||
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
<Row OnBreakpoint="HandleBreakpoint">
|
||||
Current break point: @current?.Name
|
||||
@foreach (var type in types)
|
||||
{
|
||||
if (type.Width < current?.Width)
|
||||
{
|
||||
<Tag Color="blue">@type.Name</Tag>
|
||||
}
|
||||
}
|
||||
</Row>
|
||||
|
||||
@code{
|
||||
|
||||
BreakpointType[] types = new[] { BreakpointType.Xxl, BreakpointType.Xl, BreakpointType.Lg, BreakpointType.Md, BreakpointType.Sm, BreakpointType.Xs };
|
||||
|
||||
BreakpointType current;
|
||||
|
||||
void HandleBreakpoint(BreakpointType breakpoint)
|
||||
{
|
||||
current = breakpoint;
|
||||
}
|
||||
}
|
@ -8,9 +8,11 @@ title:
|
||||
## zh-CN
|
||||
|
||||
从堆叠到水平排列。
|
||||
使用单一的一组 `Row` 和 `Col` 栅格组件,就可以创建一个基本的栅格系统,所有列(Col)必须放在 `Row` 内。。
|
||||
|
||||
使用单一的一组 `Row` 和 `Col` 栅格组件,就可以创建一个基本的栅格系统,所有列(Col)必须放在 `Row` 内。
|
||||
|
||||
## en-US
|
||||
|
||||
From the stack to the horizontal arrangement.
|
||||
|
||||
You can create a basic grid system by using a single set of `Row` and `Col` grid assembly, all of the columns (Col) must be placed in `Row`.
|
@ -12,3 +12,4 @@ title:
|
||||
## en-US
|
||||
|
||||
Child elements vertically aligned.
|
||||
|
15
site/AntDesign.Docs/Demos/Components/Grid/demo/flex-order.md
Normal file
15
site/AntDesign.Docs/Demos/Components/Grid/demo/flex-order.md
Normal file
@ -0,0 +1,15 @@
|
||||
---
|
||||
order: 6
|
||||
title:
|
||||
zh-CN: 排序
|
||||
en-US: Order
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
通过 `order` 来改变元素的排序。
|
||||
|
||||
## en-US
|
||||
|
||||
To change the element sort by `order`.
|
||||
|
@ -0,0 +1,15 @@
|
||||
---
|
||||
order: 7
|
||||
title:
|
||||
zh-CN: Flex 填充
|
||||
en-US: Flex Stretch
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
Col 提供 `flex` 属性以支持填充。
|
||||
|
||||
## en-US
|
||||
|
||||
Col provides `flex` prop to support fill rest.
|
||||
|
17
site/AntDesign.Docs/Demos/Components/Grid/demo/flex.md
Normal file
17
site/AntDesign.Docs/Demos/Components/Grid/demo/flex.md
Normal file
@ -0,0 +1,17 @@
|
||||
---
|
||||
order: 4
|
||||
title:
|
||||
zh-CN: 排版
|
||||
en-US: Typesetting
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
布局基础。
|
||||
|
||||
子元素根据不同的值 `start`,`center`,`end`,`space-between`,`space-around`,分别定义其在父节点里面的排版方式。
|
||||
|
||||
## en-US
|
||||
|
||||
Child elements depending on the value of the `start`,`center`, `end`,`space-between`, `space-around`, which are defined in its parent node typesetting mode.
|
||||
|
@ -7,13 +7,23 @@ title:
|
||||
|
||||
## zh-CN
|
||||
|
||||
栅格常常需要和间隔进行配合,你可以使用 `Row` 的 `gutter` 属性,我们推荐使用 `(16+8n)px` 作为栅格间隔。(n 是自然数)
|
||||
如果要支持响应式,可以写成 { xs: 8, sm: 16, md: 24, lg: 32 }。
|
||||
如果需要垂直间距,可以写成数组形式 [水平间距, 垂直间距] [16, { xs: 8, sm: 16, md: 24, lg: 32 }]。
|
||||
数组形式垂直间距在 `3.24.0` 之后支持。
|
||||
栅格常常需要和间隔进行配合,你可以使用 `Row` 的 `gutter` 属性,我们推荐使用 `(16+8n)px` 作为栅格间隔(n 是自然数)。
|
||||
|
||||
如果要支持响应式,可以写成 `{ xs: 8, sm: 16, md: 24, lg: 32 }`。
|
||||
|
||||
如果需要垂直间距,可以写成数组形式 `[水平间距, 垂直间距]` `[16, { xs: 8, sm: 16, md: 24, lg: 32 }]`。
|
||||
|
||||
## en-US
|
||||
|
||||
You can use the `gutter` property of `Row` as grid spacing, we recommend set it to `(16 + 8n) px`. (`n` stands for natural number.)
|
||||
You can use the `gutter` property of `Row` as grid spacing, we recommend set it to `(16 + 8n) px` (`n` stands for natural number).
|
||||
|
||||
You can set it to a object like `{ xs: 8, sm: 16, md: 24, lg: 32 }` for responsive design.
|
||||
You can use a array to set vertical spacing, `[horizontal, vertical]` `[16, { xs: 8, sm: 16, md: 24, lg: 32 }]`. vertical gutter was supported after `3.24.0`
|
||||
|
||||
You can use a array to set vertical spacing, `[horizontal, vertical]` `[16, { xs: 8, sm: 16, md: 24, lg: 32 }]`.
|
||||
|
||||
|
||||
<style>
|
||||
[data-theme="dark"] .gutter-box {
|
||||
background: #028ac8;
|
||||
}
|
||||
</style>
|
||||
|
17
site/AntDesign.Docs/Demos/Components/Grid/demo/offset.md
Normal file
17
site/AntDesign.Docs/Demos/Components/Grid/demo/offset.md
Normal file
@ -0,0 +1,17 @@
|
||||
---
|
||||
order: 2
|
||||
title:
|
||||
zh-CN: 左右偏移
|
||||
en-US: Column offset
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
列偏移。
|
||||
|
||||
使用 `offset` 可以将列向右侧偏。例如,`offset={4}` 将元素向右侧偏移了 4 个列(column)的宽度。
|
||||
|
||||
## en-US
|
||||
|
||||
`offset` can set the column to the right side. For example, using `offset = {4}` can set the element shifted to the right four columns width.
|
||||
|
149
site/AntDesign.Docs/Demos/Components/Grid/demo/playground.md
Normal file
149
site/AntDesign.Docs/Demos/Components/Grid/demo/playground.md
Normal file
@ -0,0 +1,149 @@
|
||||
---
|
||||
order: 10
|
||||
title:
|
||||
zh-CN: 栅格配置器
|
||||
en-US: Playground
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
可以简单配置几种等分栅格和间距。
|
||||
|
||||
## en-US
|
||||
|
||||
A simple playground for column count and gutter.
|
||||
|
||||
```jsx
|
||||
import { Row, Col, Slider } from 'antd';
|
||||
|
||||
const gutters = {};
|
||||
const vgutters = {};
|
||||
const colCounts = {};
|
||||
|
||||
[8, 16, 24, 32, 40, 48].forEach((value, i) => {
|
||||
gutters[i] = value;
|
||||
});
|
||||
[8, 16, 24, 32, 40, 48].forEach((value, i) => {
|
||||
vgutters[i] = value;
|
||||
});
|
||||
[2, 3, 4, 6, 8, 12].forEach((value, i) => {
|
||||
colCounts[i] = value;
|
||||
});
|
||||
|
||||
class App extends React.Component {
|
||||
state = {
|
||||
gutterKey: 1,
|
||||
vgutterKey: 1,
|
||||
colCountKey: 2,
|
||||
};
|
||||
|
||||
onGutterChange = gutterKey => {
|
||||
this.setState({ gutterKey });
|
||||
};
|
||||
|
||||
onVGutterChange = vgutterKey => {
|
||||
this.setState({ vgutterKey });
|
||||
};
|
||||
|
||||
onColCountChange = colCountKey => {
|
||||
this.setState({ colCountKey });
|
||||
};
|
||||
|
||||
render() {
|
||||
const { gutterKey, vgutterKey, colCountKey } = this.state;
|
||||
const cols = [];
|
||||
const colCount = colCounts[colCountKey];
|
||||
let colCode = '';
|
||||
for (let i = 0; i < colCount; i++) {
|
||||
cols.push(
|
||||
<Col key={i.toString()} span={24 / colCount}>
|
||||
<div>Column</div>
|
||||
</Col>,
|
||||
);
|
||||
colCode += ` <Col span={${24 / colCount}} />\n`;
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<span>Horizontal Gutter (px): </span>
|
||||
<div style={{ width: '50%' }}>
|
||||
<Slider
|
||||
min={0}
|
||||
max={Object.keys(gutters).length - 1}
|
||||
value={gutterKey}
|
||||
onChange={this.onGutterChange}
|
||||
marks={gutters}
|
||||
step={null}
|
||||
tipFormatter={value => gutters[value]}
|
||||
/>
|
||||
</div>
|
||||
<span>Vertical Gutter (px): </span>
|
||||
<div style={{ width: '50%' }}>
|
||||
<Slider
|
||||
min={0}
|
||||
max={Object.keys(vgutters).length - 1}
|
||||
value={vgutterKey}
|
||||
onChange={this.onVGutterChange}
|
||||
marks={vgutters}
|
||||
step={null}
|
||||
tipFormatter={value => vgutters[value]}
|
||||
/>
|
||||
</div>
|
||||
<span>Column Count:</span>
|
||||
<div style={{ width: '50%', marginBottom: 48 }}>
|
||||
<Slider
|
||||
min={0}
|
||||
max={Object.keys(colCounts).length - 1}
|
||||
value={colCountKey}
|
||||
onChange={this.onColCountChange}
|
||||
marks={colCounts}
|
||||
step={null}
|
||||
tipFormatter={value => colCounts[value]}
|
||||
/>
|
||||
</div>
|
||||
<Row gutter={[gutters[gutterKey], vgutters[vgutterKey]]}>
|
||||
{cols}
|
||||
{cols}
|
||||
</Row>
|
||||
Another Row:
|
||||
<Row gutter={[gutters[gutterKey], vgutters[vgutterKey]]}>{cols}</Row>
|
||||
<pre className="demo-code">{`<Row gutter={[${gutters[gutterKey]}, ${vgutters[vgutterKey]}]}>\n${colCode}\n${colCode}</Row>`}</pre>
|
||||
<pre className="demo-code">{`<Row gutter={[${gutters[gutterKey]}, ${vgutters[vgutterKey]}]}>\n${colCode}</Row>`}</pre>
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ReactDOM.render(<App />, mountNode);
|
||||
```
|
||||
|
||||
```css
|
||||
#components-grid-demo-playground [class~='ant-col'] {
|
||||
background: transparent;
|
||||
border: 0;
|
||||
}
|
||||
#components-grid-demo-playground [class~='ant-col'] > div {
|
||||
height: 120px;
|
||||
font-size: 14px;
|
||||
line-height: 120px;
|
||||
background: #0092ff;
|
||||
border-radius: 4px;
|
||||
}
|
||||
#components-grid-demo-playground pre {
|
||||
padding: 8px 16px;
|
||||
font-size: 13px;
|
||||
background: #f9f9f9;
|
||||
border-radius: 6px;
|
||||
}
|
||||
#components-grid-demo-playground pre.demo-code {
|
||||
direction: ltr;
|
||||
}
|
||||
#components-grid-demo-playground .ant-col {
|
||||
padding: 0;
|
||||
}
|
||||
```
|
||||
|
||||
<style>
|
||||
[data-theme="dark"] #components-grid-demo-playground [class~='ant-col'] > div {
|
||||
background: #028ac8;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,16 @@
|
||||
---
|
||||
order: 9
|
||||
title:
|
||||
zh-CN: 其他属性的响应式
|
||||
en-US: More responsive
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
`span` `pull` `push` `offset` `order` 属性可以通过内嵌到 `xs` `sm` `md` `lg` `xl` `xxl` 属性中来使用。
|
||||
|
||||
其中 `xs={6}` 相当于 `xs={{ span: 6 }}`。
|
||||
|
||||
## en-US
|
||||
|
||||
`span` `pull` `push` `offset` `order` property can be embedded into `xs` `sm` `md` `lg` `xl` `xxl` properties to use, where `xs={6}` is equivalent to `xs={{span: 6}}`.
|
14
site/AntDesign.Docs/Demos/Components/Grid/demo/responsive.md
Normal file
14
site/AntDesign.Docs/Demos/Components/Grid/demo/responsive.md
Normal file
@ -0,0 +1,14 @@
|
||||
---
|
||||
order: 8
|
||||
title:
|
||||
zh-CN: 响应式布局
|
||||
en-US: Responsive
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
参照 Bootstrap 的 [响应式设计](http://getbootstrap.com/css/#grid-media-queries),预设六个响应尺寸:`xs` `sm` `md` `lg` `xl` `xxl`。
|
||||
|
||||
## en-US
|
||||
|
||||
Referring to the Bootstrap [responsive design](http://getbootstrap.com/css/#grid-media-queries), here preset six dimensions: `xs` `sm` `md` `lg` `xl` `xxl`.
|
@ -8,8 +8,10 @@ title:
|
||||
## zh-CN
|
||||
|
||||
列排序。
|
||||
通过使用 push 和 pull 类就可以很容易的改变列(column)的顺序。
|
||||
|
||||
通过使用 `push` 和 `pull` 类就可以很容易的改变列(column)的顺序。
|
||||
|
||||
## en-US
|
||||
|
||||
By using `push` and `pull` class you can easily change column order.
|
||||
|
@ -0,0 +1,15 @@
|
||||
---
|
||||
order: 10
|
||||
title:
|
||||
zh-CN: 监听 Breakpoint
|
||||
en-US: Breakpoint
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
使用 `OnBreakpoint` 事件个性化布局。
|
||||
|
||||
## en-US
|
||||
|
||||
Use `OnBreakpoint` provide personalized layout.
|
||||
|
@ -15,6 +15,8 @@ A basic widget for getting the user input is a text field. Keyboard and mouse ca
|
||||
|
||||
## API
|
||||
|
||||
### Common API
|
||||
|
||||
| Property | Description | Type | Default Value |
|
||||
| --- | --- | --- | --- |
|
||||
| AddOnBefore | The label text displayed before (on the left side of) the input field. | RenderFragment | - |
|
||||
@ -32,3 +34,9 @@ A basic widget for getting the user input is a text field. Keyboard and mouse ca
|
||||
| OnChange |callback when the content is change | function(e) | 0 |
|
||||
| OnPressEnter |The callback function that is triggered when Enter key is pressed. | function(e) | - |
|
||||
| OnInput |callback when user input | function(e) | - |
|
||||
|
||||
### TextArea
|
||||
|
||||
| Property | Description | Type | Default | Version |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| DefaultToEmptyString | When `false`, value will be set to `null` when content is empty or whitespace. When `true`, value will be set to empty string. | boolean | false |
|
@ -87,8 +87,6 @@
|
||||
|
||||
public async Task OnChange(QueryModel<WeatherForecast> queryModel)
|
||||
{
|
||||
forecasts = await GetForecastAsync(queryModel.PageIndex, queryModel.PageSize);
|
||||
_total = 50;
|
||||
Console.WriteLine(JsonSerializer.Serialize(queryModel));
|
||||
}
|
||||
|
||||
|
@ -1,16 +1,16 @@
|
||||
<Table @ref=" table" TItem="TestData" DataSource="@testData">
|
||||
@using AntDesign.TableModels
|
||||
|
||||
<Table TItem="TestData" DataSource="@testData">
|
||||
<Column @bind-Field="@context.Id" Sortable/>
|
||||
<Column Title="DayOfWeek" @bind-Field="@context.DayOfWeek" Sortable/>
|
||||
<Column Title="DayOfWeek DataIndex" TData="int" DataIndex="DayOfWeek" Sortable SorterCompare="@((v1, v2) => v1 - v2)"/>
|
||||
<Column Title="N1.N12.N2A DataIndex" TData="string" DataIndex=@("N1.N12[\"test\"].N2A") Sortable SorterCompare="@((v1, v2) => string.CompareOrdinal(v1, v2))"/>
|
||||
<Column Title="DayOfWeek DataIndex" TData="int" DataIndex="DayOfWeek" Sortable SorterCompare="@((v1, v2) => v1 - v2)" Filters="DayOfWeekFilter" OnFilter="(a, b) => a == b"/>
|
||||
<Column Title="N1.N12.N2A DataIndex" TData="string" DataIndex=@("N1.N12[\"test\"].N2A") Sortable/>
|
||||
<Column Title="N1.N1A DataIndex Nullable" TData="int?" DataIndex="N1.N1A" Sortable SorterCompare="CompareNullableInt"/>
|
||||
<Column Title="Time" TData="DateTime?" DataIndex=@(@"N1.N12[""test""].Time") Format="yyyy-MM-dd hh:mm:ss" Sortable SorterCompare="_dateTimeCompare"></Column>
|
||||
</Table>
|
||||
|
||||
@code {
|
||||
|
||||
ITable table;
|
||||
|
||||
TestData[] testData;
|
||||
|
||||
public class TestData
|
||||
@ -40,6 +40,17 @@
|
||||
public DateTime? Time { get; set; }
|
||||
}
|
||||
|
||||
public TableFilter<int>[] DayOfWeekFilter =
|
||||
{
|
||||
new() {Text = "Monday", Value = 1},
|
||||
new() {Text = "Tuesday", Value = 2},
|
||||
new() {Text = "Wednesdays", Value = 3},
|
||||
new() {Text = "Thursday", Value = 4},
|
||||
new() {Text = "Friday", Value = 5},
|
||||
new() {Text = "Saturday", Value = 6},
|
||||
new() {Text = "Sunday", Value = 7},
|
||||
};
|
||||
|
||||
public string[] DayName = {"None", "Monday", "Tuesday", "Wednesdays", "Thursday", "Friday", "Saturday", "Sunday"};
|
||||
|
||||
Func<DateTime?, DateTime?, int> _dateTimeCompare = (t1, t2) =>
|
||||
@ -63,7 +74,7 @@
|
||||
|
||||
public TestData[] GetForecastAsync()
|
||||
{
|
||||
var rng = new Random();
|
||||
var rng = new Random(42);
|
||||
var startDate = new DateTime(DateTime.Today.Year - 5, 1, 1);
|
||||
var range = (DateTime.Today - startDate).TotalSeconds;
|
||||
return Enumerable.Range(0, 5).Select(index =>
|
||||
|
@ -1,60 +1,80 @@
|
||||
@using System.ComponentModel
|
||||
@implements IDisposable
|
||||
@using System.ComponentModel
|
||||
@using System.Reflection
|
||||
@using System.Web
|
||||
|
||||
|
||||
<div class="router-pagging-table">
|
||||
<Input @bind-Value="_url" OnPressEnter="()=> navigation.NavigateTo(_url,true)" />
|
||||
<Table @ref="table"
|
||||
DataSource="@forecasts"
|
||||
Total="_total"
|
||||
Loading="_loading"
|
||||
@bind-PageIndex="_pageIndex"
|
||||
@bind-PageSize="_pageSize"
|
||||
OnPageIndexChange="fetchData"
|
||||
@bind-SelectedRows="selectedRows">
|
||||
<Selection Key="@(context.Id.ToString())" />
|
||||
<Column @bind-Field="@context.Id" Sortable />
|
||||
<Column @bind-Field="@context.Date" Format="yyyy-MM-dd" Sortable />
|
||||
<Column @bind-Field="@context.TemperatureC" Sortable />
|
||||
<Column Title="Temp. (F)" Field="@context.TemperatureF" />
|
||||
<Column @bind-Field="@context.Summary" Sortable />
|
||||
<Input @bind-Value="_url" OnPressEnter="() => _navigation.NavigateTo(_url, true)"/>
|
||||
<Table
|
||||
DataSource="@_forecasts"
|
||||
Total="_total"
|
||||
Loading="_loading"
|
||||
PageIndex="@_pageIndex"
|
||||
PageSize="@_pageSize"
|
||||
OnPageIndexChange="PageIndexChanged">
|
||||
<Column @bind-Field="@context.Id"/>
|
||||
<Column @bind-Field="@context.Date" Format="yyyy-MM-dd"/>
|
||||
<Column @bind-Field="@context.TemperatureC"/>
|
||||
<Column Title="Temp. (F)" Field="@context.TemperatureF"/>
|
||||
<Column @bind-Field="@context.Summary"/>
|
||||
</Table>
|
||||
|
||||
<br />
|
||||
<br/>
|
||||
<p>PageIndex: @_pageIndex | PageSize: @_pageSize | Total: @_total</p>
|
||||
</div>
|
||||
|
||||
@inject NavigationManager navigation
|
||||
@inject NavigationManager _navigation
|
||||
|
||||
@code {
|
||||
|
||||
WeatherForecast[] forecasts;
|
||||
|
||||
IEnumerable<WeatherForecast> selectedRows;
|
||||
ITable table;
|
||||
WeatherForecast[] _forecasts;
|
||||
|
||||
int _pageIndex = 1;
|
||||
|
||||
int _pageSize = 5;
|
||||
|
||||
int _total = 0;
|
||||
|
||||
string _url;
|
||||
|
||||
bool _loading;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
_url = navigation.Uri;
|
||||
var query = HttpUtility.ParseQueryString(_url);
|
||||
_pageIndex = int.TryParse(query["page"], out var index) ? index > 0 ? index : 1 : 1;
|
||||
_pageSize = int.TryParse(query["size"], out var size) ? size > 0 ? size : 5 : 5;
|
||||
|
||||
_loading = true;
|
||||
forecasts = await GetForecastAsync(_pageIndex, _pageSize);
|
||||
_url = _navigation.Uri;
|
||||
_total = 50;
|
||||
_loading = false;
|
||||
_navigation.LocationChanged += LocationChanged;
|
||||
LoadTableParameter();
|
||||
await LoadDataAsync();
|
||||
}
|
||||
|
||||
void fetchData(PaginationEventArgs args)
|
||||
private async void LocationChanged(object sender, LocationChangedEventArgs e)
|
||||
{
|
||||
navigation.NavigateTo($"mock?type={GetType().ToString().Replace($"{Assembly.GetExecutingAssembly().GetName().Name}.", "")}&page={args.Page}&size={args.PageSize}");
|
||||
_url = e.Location;
|
||||
LoadTableParameter();
|
||||
await LoadDataAsync();
|
||||
}
|
||||
|
||||
private void LoadTableParameter()
|
||||
{
|
||||
var uri = _navigation.ToAbsoluteUri(_url);
|
||||
var query = HttpUtility.ParseQueryString(uri.Query);
|
||||
_pageIndex = int.TryParse(query["page"], out var index) ? index > 0 ? index : 1 : 1;
|
||||
_pageSize = int.TryParse(query["size"], out var size) ? size > 0 ? size : 5 : 5;
|
||||
}
|
||||
|
||||
private void PageIndexChanged(PaginationEventArgs args)
|
||||
{
|
||||
_navigation.NavigateTo($"mock?type={GetType().ToString().Replace($"{Assembly.GetExecutingAssembly().GetName().Name}.", "")}&page={args.Page}&size={args.PageSize}");
|
||||
}
|
||||
|
||||
private async Task LoadDataAsync()
|
||||
{
|
||||
_loading = true;
|
||||
StateHasChanged();
|
||||
_forecasts = await GetForecastAsync(_pageIndex, _pageSize);
|
||||
_loading = false;
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
public class WeatherForecast
|
||||
@ -82,7 +102,7 @@
|
||||
|
||||
public async Task<WeatherForecast[]> GetForecastAsync(int pageIndex, int pageSize)
|
||||
{
|
||||
await Task.Delay(1000);
|
||||
await Task.Delay(200);
|
||||
var rng = new Random();
|
||||
return await Task.FromResult(Enumerable.Range((pageIndex - 1) * pageSize + 1, pageSize).Select(index =>
|
||||
{
|
||||
@ -97,8 +117,13 @@
|
||||
};
|
||||
}).ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_navigation.LocationChanged -= LocationChanged;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
<style>
|
||||
.router-pagging-table {
|
||||
|
@ -1,6 +1,6 @@
|
||||
---
|
||||
order: 2
|
||||
iframe: 480
|
||||
iframe: 550
|
||||
title:
|
||||
en-US: Router pagging
|
||||
zh-CN: 通过路由参数进行翻页
|
||||
|
@ -110,7 +110,8 @@ namespace AntDesign.Docs.Services
|
||||
_showCaseCache ??= new ConcurrentCache<string, RenderFragment>();
|
||||
return _showCaseCache.GetOrAdd(type, t =>
|
||||
{
|
||||
var showCase = Type.GetType($"{Assembly.GetExecutingAssembly().GetName().Name}.{type}");
|
||||
var showCase = Type.GetType($"{Assembly.GetExecutingAssembly().GetName().Name}.{type}") ?? typeof(Template);
|
||||
|
||||
void ShowCase(RenderTreeBuilder builder)
|
||||
{
|
||||
builder.OpenComponent(0, showCase);
|
||||
|
@ -8,7 +8,8 @@ namespace AntDesign.Tests.Grid
|
||||
[Fact]
|
||||
public void Render_with_defaults()
|
||||
{
|
||||
var cut = Context.RenderComponent<AntDesign.Col>(p =>{
|
||||
var cut = Context.RenderComponent<AntDesign.Col>(p =>
|
||||
{
|
||||
p.AddChildContent("Contents");
|
||||
});
|
||||
cut.MarkupMatches(@"
|
||||
@ -19,7 +20,8 @@ namespace AntDesign.Tests.Grid
|
||||
[Fact]
|
||||
public void Render_with_all_options()
|
||||
{
|
||||
var cut = Context.RenderComponent<AntDesign.Col>(p =>{
|
||||
var cut = Context.RenderComponent<AntDesign.Col>(p =>
|
||||
{
|
||||
p.Add(x => x.Flex, 1);
|
||||
p.Add(x => x.Span, 2);
|
||||
p.Add(x => x.Order, 3);
|
||||
@ -29,14 +31,15 @@ namespace AntDesign.Tests.Grid
|
||||
p.AddChildContent("Contents");
|
||||
});
|
||||
cut.MarkupMatches(@"
|
||||
<div class=""ant-col ant-col-2 ant-col-order-3 ant-col-offset-4 ant-col-pull-6 ant-col-push-5"" style="" "" id:ignore>Contents</div>
|
||||
<div class=""ant-col ant-col-2 ant-col-order-3 ant-col-offset-4 ant-col-pull-6 ant-col-push-5"" style=""flex: 1 1 auto"" id:ignore>Contents</div>
|
||||
");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Render_with_column_int_span()
|
||||
{
|
||||
var cut = Context.RenderComponent<AntDesign.Col>(p =>{
|
||||
var cut = Context.RenderComponent<AntDesign.Col>(p =>
|
||||
{
|
||||
p.Add(x => x.Span, 2);
|
||||
p.AddChildContent("Contents");
|
||||
});
|
||||
@ -48,7 +51,8 @@ namespace AntDesign.Tests.Grid
|
||||
[Fact]
|
||||
public void Render_with_column_string_span()
|
||||
{
|
||||
var cut = Context.RenderComponent<AntDesign.Col>(p =>{
|
||||
var cut = Context.RenderComponent<AntDesign.Col>(p =>
|
||||
{
|
||||
p.Add(x => x.Span, "3");
|
||||
p.AddChildContent("Contents");
|
||||
});
|
||||
@ -64,7 +68,8 @@ namespace AntDesign.Tests.Grid
|
||||
[Fact]
|
||||
public void Render_with_column_span_and_xs_column_span()
|
||||
{
|
||||
var cut = Context.RenderComponent<AntDesign.Col>(p =>{
|
||||
var cut = Context.RenderComponent<AntDesign.Col>(p =>
|
||||
{
|
||||
p.Add(x => x.Span, 5);
|
||||
p.Add(x => x.Xs, 6);
|
||||
p.AddChildContent("Contents");
|
||||
@ -81,10 +86,12 @@ namespace AntDesign.Tests.Grid
|
||||
[Fact]
|
||||
public void Render_with_all_xs_options()
|
||||
{
|
||||
var cut = Context.RenderComponent<AntDesign.Col>(p =>{
|
||||
var cut = Context.RenderComponent<AntDesign.Col>(p =>
|
||||
{
|
||||
p.Add(
|
||||
x => x.Xs,
|
||||
new AntDesign.EmbeddedProperty {
|
||||
new AntDesign.EmbeddedProperty
|
||||
{
|
||||
Span = 2,
|
||||
Order = 3,
|
||||
Offset = 4,
|
||||
@ -101,7 +108,8 @@ namespace AntDesign.Tests.Grid
|
||||
[Fact]
|
||||
public void Render_with_xs_column_int_span()
|
||||
{
|
||||
var cut = Context.RenderComponent<AntDesign.Col>(p =>{
|
||||
var cut = Context.RenderComponent<AntDesign.Col>(p =>
|
||||
{
|
||||
p.Add(x => x.Xs, 4);
|
||||
p.AddChildContent("Contents");
|
||||
});
|
||||
@ -113,7 +121,8 @@ namespace AntDesign.Tests.Grid
|
||||
[Fact]
|
||||
public void Render_with_xs_column_embedded_span()
|
||||
{
|
||||
var cut = Context.RenderComponent<AntDesign.Col>(p =>{
|
||||
var cut = Context.RenderComponent<AntDesign.Col>(p =>
|
||||
{
|
||||
p.Add(x => x.Xs, new AntDesign.EmbeddedProperty { Span = 3 });
|
||||
p.AddChildContent("Contents");
|
||||
});
|
||||
@ -129,7 +138,8 @@ namespace AntDesign.Tests.Grid
|
||||
[Fact]
|
||||
public void Render_with_sm_column_int_span()
|
||||
{
|
||||
var cut = Context.RenderComponent<AntDesign.Col>(p =>{
|
||||
var cut = Context.RenderComponent<AntDesign.Col>(p =>
|
||||
{
|
||||
p.Add(x => x.Sm, 2);
|
||||
p.AddChildContent("Contents");
|
||||
});
|
||||
@ -145,7 +155,8 @@ namespace AntDesign.Tests.Grid
|
||||
[Fact]
|
||||
public void Render_with_md_column_int_span()
|
||||
{
|
||||
var cut = Context.RenderComponent<AntDesign.Col>(p =>{
|
||||
var cut = Context.RenderComponent<AntDesign.Col>(p =>
|
||||
{
|
||||
p.Add(x => x.Md, 2);
|
||||
p.AddChildContent("Contents");
|
||||
});
|
||||
@ -161,7 +172,8 @@ namespace AntDesign.Tests.Grid
|
||||
[Fact]
|
||||
public void Render_with_lg_column_int_span()
|
||||
{
|
||||
var cut = Context.RenderComponent<AntDesign.Col>(p =>{
|
||||
var cut = Context.RenderComponent<AntDesign.Col>(p =>
|
||||
{
|
||||
p.Add(x => x.Lg, 2);
|
||||
p.AddChildContent("Contents");
|
||||
});
|
||||
@ -177,7 +189,8 @@ namespace AntDesign.Tests.Grid
|
||||
[Fact]
|
||||
public void Render_with_xl_column_int_span()
|
||||
{
|
||||
var cut = Context.RenderComponent<AntDesign.Col>(p =>{
|
||||
var cut = Context.RenderComponent<AntDesign.Col>(p =>
|
||||
{
|
||||
p.Add(x => x.Xl, 2);
|
||||
p.AddChildContent("Contents");
|
||||
});
|
||||
@ -193,7 +206,8 @@ namespace AntDesign.Tests.Grid
|
||||
[Fact]
|
||||
public void Render_with_xxl_column_int_span()
|
||||
{
|
||||
var cut = Context.RenderComponent<AntDesign.Col>(p =>{
|
||||
var cut = Context.RenderComponent<AntDesign.Col>(p =>
|
||||
{
|
||||
p.Add(x => x.Xxl, 2);
|
||||
p.AddChildContent("Contents");
|
||||
});
|
||||
|
100
tests/Core/Helpers/DateHelperTests.cs
Normal file
100
tests/Core/Helpers/DateHelperTests.cs
Normal file
@ -0,0 +1,100 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Xunit;
|
||||
|
||||
namespace AntDesign.Tests.Core.Helpers
|
||||
{
|
||||
public class DateHelperTests
|
||||
{
|
||||
[Theory]
|
||||
[MemberData(nameof(GetNextStartDateOfDecade_Values))]
|
||||
public void GetNextStartDateOfDecade(DateTime currentDateTime, DateTime exceptedDateTime)
|
||||
{
|
||||
Assert.Equal(exceptedDateTime, DateHelper.GetNextStartDateOfDecade(currentDateTime));
|
||||
}
|
||||
|
||||
public static List<object[]> GetNextStartDateOfDecade_Values => new()
|
||||
{
|
||||
new object[] { DateTime.Parse("2020-01-04 05:34:55"), DateTime.Parse("2030-01-01 00:00:00") },
|
||||
new object[] { DateTime.Parse("2018-01-04 05:34:55"), DateTime.Parse("2020-01-01 00:00:00") },
|
||||
new object[] { DateTime.Parse("2015-07-24 05:34:55"), DateTime.Parse("2020-01-01 00:00:00") },
|
||||
new object[] { DateTime.Parse("1800-07-24 05:34:55"), DateTime.Parse("1810-01-01 00:00:00") },
|
||||
new object[] { DateTime.Parse("1867-07-24 05:34:55"), DateTime.Parse("1870-01-01 00:00:00") },
|
||||
new object[] { DateTime.MinValue, DateTime.MinValue.AddYears(10) },
|
||||
new object[] { DateTime.MaxValue, DateTime.Parse($"{DateTime.MaxValue.Year}-01-01 00:00:00") },
|
||||
};
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(GetNextStartDateOfYear_Values))]
|
||||
public void GetNextStartDateOfYear(DateTime currentDateTime, DateTime exceptedDateTime)
|
||||
{
|
||||
Assert.Equal(exceptedDateTime, DateHelper.GetNextStartDateOfYear(currentDateTime));
|
||||
}
|
||||
|
||||
public static List<object[]> GetNextStartDateOfYear_Values => new()
|
||||
{
|
||||
new object[] { DateTime.Parse("2020-01-04 05:34:55"), DateTime.Parse("2021-01-01 00:00:00") },
|
||||
new object[] { DateTime.Parse("2018-01-04 05:34:55"), DateTime.Parse("2019-01-01 00:00:00") },
|
||||
new object[] { DateTime.Parse("2015-07-24 05:34:55"), DateTime.Parse("2016-01-01 00:00:00") },
|
||||
new object[] { DateTime.Parse("1800-07-24 05:34:55"), DateTime.Parse("1801-01-01 00:00:00") },
|
||||
new object[] { DateTime.Parse("1867-07-24 05:34:55"), DateTime.Parse("1868-01-01 00:00:00") },
|
||||
new object[] { DateTime.MinValue, DateTime.MinValue.AddYears(1) },
|
||||
new object[] { DateTime.MaxValue, DateTime.Parse($"{DateTime.MaxValue.Year}-01-01 00:00:00") },
|
||||
};
|
||||
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(GetNextStartDateOfQuarter_Values))]
|
||||
public void GetNextStartDateOfQuarter(DateTime currentDateTime, DateTime exceptedDateTime)
|
||||
{
|
||||
Assert.Equal(exceptedDateTime, DateHelper.GetNextStartDateOfQuarter(currentDateTime));
|
||||
}
|
||||
|
||||
public static List<object[]> GetNextStartDateOfQuarter_Values => new()
|
||||
{
|
||||
new object[] { DateTime.Parse("2020-01-04 05:34:55"), DateTime.Parse("2020-04-01 00:00:00") },
|
||||
new object[] { DateTime.Parse("2018-01-04 05:34:55"), DateTime.Parse("2018-04-01 00:00:00") },
|
||||
new object[] { DateTime.Parse("2015-07-24 05:34:55"), DateTime.Parse("2015-10-01 00:00:00") },
|
||||
new object[] { DateTime.Parse("1800-11-24 05:34:55"), DateTime.Parse("1801-01-01 00:00:00") },
|
||||
new object[] { DateTime.Parse("1867-07-24 05:34:55"), DateTime.Parse("1867-10-01 00:00:00") },
|
||||
new object[] { DateTime.MinValue, DateTime.MinValue.AddMonths(3) },
|
||||
new object[] { DateTime.MaxValue, DateTime.Parse($"{DateTime.MaxValue.Year}-10-01 00:00:00") },
|
||||
};
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(GetNextStartDateOfMonth_Values))]
|
||||
public void GetNextStartDateOfMonth(DateTime currentDateTime, DateTime exceptedDateTime)
|
||||
{
|
||||
Assert.Equal(exceptedDateTime, DateHelper.GetNextStartDateOfMonth(currentDateTime));
|
||||
}
|
||||
|
||||
public static List<object[]> GetNextStartDateOfMonth_Values => new()
|
||||
{
|
||||
new object[] { DateTime.Parse("2020-01-04 05:34:55"), DateTime.Parse("2020-02-01 00:00:00") },
|
||||
new object[] { DateTime.Parse("2018-01-04 05:34:55"), DateTime.Parse("2018-02-01 00:00:00") },
|
||||
new object[] { DateTime.Parse("2015-07-24 05:34:55"), DateTime.Parse("2015-08-01 00:00:00") },
|
||||
new object[] { DateTime.Parse("1800-12-24 05:34:55"), DateTime.Parse("1801-01-01 00:00:00") },
|
||||
new object[] { DateTime.Parse("1867-07-24 05:34:55"), DateTime.Parse("1867-08-01 00:00:00") },
|
||||
new object[] { DateTime.MinValue, DateTime.MinValue.AddMonths(1) },
|
||||
new object[] { DateTime.MaxValue, DateTime.Parse($"{DateTime.MaxValue.Year}-12-01 00:00:00") },
|
||||
};
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(GetNextStartDateOfDay_Values))]
|
||||
public void GetNextStartDateOfDay(DateTime currentDateTime, DateTime exceptedDateTime)
|
||||
{
|
||||
Assert.Equal(exceptedDateTime, DateHelper.GetNextStartDateOfDay(currentDateTime));
|
||||
}
|
||||
|
||||
public static List<object[]> GetNextStartDateOfDay_Values => new()
|
||||
{
|
||||
new object[] { DateTime.Parse("2020-01-04 05:34:55"), DateTime.Parse("2020-01-05 00:00:00") },
|
||||
new object[] { DateTime.Parse("2018-01-04 05:34:55"), DateTime.Parse("2018-01-05 00:00:00") },
|
||||
new object[] { DateTime.Parse("2015-07-31 05:34:55"), DateTime.Parse("2015-08-01 00:00:00") },
|
||||
new object[] { DateTime.Parse("1800-07-24 05:34:55"), DateTime.Parse("1800-07-25 00:00:00") },
|
||||
new object[] { DateTime.Parse("1867-12-24 05:34:55"), DateTime.Parse("1867-12-25 00:00:00") },
|
||||
new object[] { DateTime.MinValue, DateTime.MinValue.AddDays(1) },
|
||||
new object[] { DateTime.MaxValue, DateTime.Parse($"{DateTime.MaxValue.Year}-12-31 00:00:00") },
|
||||
};
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user