2020-06-01 14:09:28 +08:00
using System ;
using System.Collections.Generic ;
2020-09-01 17:23:31 +08:00
using System.Linq ;
using AntDesign.Core.Reflection ;
2020-06-01 14:09:28 +08:00
using AntDesign.Forms ;
using AntDesign.Internal ;
using Microsoft.AspNetCore.Components ;
using Microsoft.AspNetCore.Components.Forms ;
2020-11-27 16:41:26 +08:00
using OneOf ;
2020-06-01 14:09:28 +08:00
namespace AntDesign
{
public partial class FormItem : AntDomComponentBase , IFormItem
{
2020-07-13 12:26:09 +08:00
private static readonly Dictionary < string , object > _noneColAttributes = new Dictionary < string , object > ( ) ;
2020-06-01 14:09:28 +08:00
private readonly string _prefixCls = "ant-form-item" ;
[CascadingParameter(Name = "Form")]
private IForm Form { get ; set ; }
2020-07-13 12:26:09 +08:00
[CascadingParameter(Name = "FormItem")]
private IFormItem ParentFormItem { get ; set ; }
[CascadingParameter]
private EditContext CurrentEditContext { get ; set ; }
2020-06-01 14:09:28 +08:00
[Parameter]
public RenderFragment ChildContent { get ; set ; }
[Parameter]
public string Label { get ; set ; }
2021-04-02 23:10:37 +08:00
[Parameter]
public RenderFragment LabelTemplate { get ; set ; }
2020-06-01 14:09:28 +08:00
[Parameter]
public ColLayoutParam LabelCol { get ; set ; }
2021-04-02 23:13:44 +08:00
[Parameter]
public AntLabelAlignType ? LabelAlign { get ; set ; }
2020-11-27 16:41:26 +08:00
[Parameter]
public OneOf < string , int > LabelColSpan
{
get { return LabelCol ? . Span ? ? null ; }
set
{
if ( LabelCol = = null ) LabelCol = new ColLayoutParam ( ) ;
LabelCol . Span = value ;
}
}
[Parameter]
public OneOf < string , int > LabelColOffset
{
get { return LabelCol ? . Offset ? ? null ; }
set
{
if ( LabelCol = = null ) LabelCol = new ColLayoutParam ( ) ;
LabelCol . Offset = value ;
}
}
2020-06-01 14:09:28 +08:00
[Parameter]
public ColLayoutParam WrapperCol { get ; set ; }
2020-11-27 16:41:26 +08:00
[Parameter]
public OneOf < string , int > WrapperColSpan
{
get { return WrapperCol ? . Span ? ? null ; }
set
{
if ( WrapperCol = = null ) WrapperCol = new ColLayoutParam ( ) ;
WrapperCol . Span = value ;
}
}
[Parameter]
public OneOf < string , int > WrapperColOffset
{
get { return WrapperCol ? . Offset ? ? null ; }
set
{
if ( WrapperCol = = null ) WrapperCol = new ColLayoutParam ( ) ;
WrapperCol . Offset = value ;
}
}
2020-07-13 12:26:09 +08:00
[Parameter]
public bool NoStyle { get ; set ; } = false ;
2020-07-13 20:37:06 +08:00
[Parameter]
public bool Required { get ; set ; } = false ;
2021-05-11 11:02:15 +08:00
/// <summary>
/// Style that will only be applied to <label></label> element.
/// Will not be applied if LabelTemplate is set.
/// </summary>
[Parameter]
public string LabelStyle { get ; set ; }
2020-06-01 14:09:28 +08:00
private EditContext EditContext = > Form ? . EditContext ;
private bool _isValid = true ;
private string _labelCls = "" ;
2020-06-02 07:28:06 +08:00
private IControlValueAccessor _control ;
2020-06-01 14:09:28 +08:00
2020-06-25 19:23:16 +08:00
private RenderFragment _formValidationMessages ;
2020-09-01 17:23:31 +08:00
private PropertyReflector _propertyReflector ;
2021-04-02 23:13:44 +08:00
private ClassMapper _labelClassMapper = new ClassMapper ( ) ;
private AntLabelAlignType ? FormLabelAlign = > LabelAlign ? ? Form . LabelAlign ;
2020-06-01 14:09:28 +08:00
protected override void OnInitialized ( )
{
base . OnInitialized ( ) ;
if ( Form = = null )
{
throw new InvalidOperationException ( "Form is null.FormItem should be childContent of Form." ) ;
}
SetClass ( ) ;
2021-04-02 23:13:44 +08:00
Form . AddFormItem ( this ) ;
2020-06-01 14:09:28 +08:00
}
protected void SetClass ( )
{
2021-04-02 23:13:44 +08:00
this . ClassMapper
2020-06-01 14:09:28 +08:00
. Add ( _prefixCls )
. If ( $"{_prefixCls}-with-help {_prefixCls}-has-error" , ( ) = > _isValid = = false )
2021-03-12 17:02:11 +08:00
. If ( $"{_prefixCls}-rtl" , ( ) = > RTL )
2020-06-01 14:09:28 +08:00
;
2021-04-02 23:13:44 +08:00
_labelClassMapper
. Add ( $"{_prefixCls}-label" )
. If ( $"{_prefixCls}-label-left" , ( ) = > FormLabelAlign = = AntLabelAlignType . Left )
;
2020-06-01 14:09:28 +08:00
}
private Dictionary < string , object > GetLabelColAttributes ( )
{
2020-07-13 12:26:09 +08:00
if ( NoStyle | | ParentFormItem ! = null )
{
return _noneColAttributes ;
}
2020-06-01 14:09:28 +08:00
ColLayoutParam labelColParameter ;
if ( LabelCol ! = null )
{
labelColParameter = LabelCol ;
}
else if ( Form . LabelCol ! = null )
{
labelColParameter = Form . LabelCol ;
}
else
{
labelColParameter = new ColLayoutParam ( ) ;
}
return labelColParameter . ToAttributes ( ) ;
}
private Dictionary < string , object > GetWrapperColAttributes ( )
{
2020-07-13 12:26:09 +08:00
if ( NoStyle | | ParentFormItem ! = null )
{
return _noneColAttributes ;
}
2020-06-01 14:09:28 +08:00
ColLayoutParam wrapperColParameter ;
if ( WrapperCol ! = null )
{
wrapperColParameter = WrapperCol ;
}
else if ( Form . WrapperCol ! = null )
{
wrapperColParameter = Form . WrapperCol ;
}
else
{
wrapperColParameter = new ColLayoutParam ( ) ;
}
return wrapperColParameter . ToAttributes ( ) ;
}
2021-04-02 23:10:37 +08:00
private string GetLabelClass ( )
{
return Required ? $"{_prefixCls}-required" : _labelCls ;
}
2020-06-01 14:09:28 +08:00
void IFormItem . AddControl < TValue > ( AntInputComponentBase < TValue > control )
{
2020-07-30 23:54:31 +08:00
if ( control . FieldIdentifier . Model = = null )
{
2021-05-06 13:42:19 +08:00
throw new InvalidOperationException ( $"Please use @bind-Value (or @bind-Values for selected components) in the control with generic type `{typeof(TValue)}`." ) ;
2020-07-30 23:54:31 +08:00
}
2020-06-01 14:09:28 +08:00
this . _control = control ;
2020-06-25 19:23:16 +08:00
CurrentEditContext . OnValidationStateChanged + = ( s , e ) = >
2020-06-01 14:09:28 +08:00
{
2021-04-20 16:03:25 +08:00
control . ValidationMessages = CurrentEditContext . GetValidationMessages ( control . FieldIdentifier ) . Distinct ( ) . ToArray ( ) ;
2020-06-25 19:23:16 +08:00
this . _isValid = ! control . ValidationMessages . Any ( ) ;
StateHasChanged ( ) ;
2020-06-01 14:09:28 +08:00
} ;
2020-06-30 22:32:36 +08:00
_formValidationMessages = builder = >
{
var i = 0 ;
builder . OpenComponent < FormValidationMessage < TValue > > ( i + + ) ;
builder . AddAttribute ( i + + , "Control" , control ) ;
builder . CloseComponent ( ) ;
} ;
2020-06-25 19:23:16 +08:00
2021-05-06 13:42:19 +08:00
if ( control . ValueExpression is not null )
_propertyReflector = PropertyReflector . Create ( control . ValueExpression ) ;
else
_propertyReflector = PropertyReflector . Create ( control . ValuesExpression ) ;
2020-09-01 17:23:31 +08:00
2020-10-25 19:03:58 +08:00
if ( _propertyReflector . RequiredAttribute ! = null )
2020-07-30 23:54:31 +08:00
{
2020-09-01 17:23:31 +08:00
_labelCls = $"{_prefixCls}-required" ;
2020-07-30 23:54:31 +08:00
}
2020-06-01 14:09:28 +08:00
}
}
}