TourIAm/TIAMSharedUI/Pages/Components/EditComponents/DynamicEditForm.razor

378 lines
19 KiB
Plaintext

@using AyCode.Core.Consts
@using System.Linq.Expressions
@using System.ComponentModel.DataAnnotations
@using AyCode.Services.Loggers
@using System.Reflection
@using AyCode.Blazor.Components.Components
@using TIAM.Entities.Products
@using TIAM.Entities.Transfers
@using TIAM.Models.Dtos.Users
@using TIAMSharedUI.Shared
@using TIAMWebApp.Shared.Application.Interfaces
@using TIAMWebApp.Shared.Application.Utility
@inject IEnumerable<IAcLogWriterClientBase> LogWriters
@inject ISessionService _sessionService
@if (isEditing)
{
<EditForm Model="@Data"
OnValidSubmit="@HandleValidSubmit"
OnInvalidSubmit="@HandleInvalidSubmit"
Context="EditFormContext">
<DataAnnotationsValidator />
<div class="card">
<div class="card-header text-center py-3">
<h4>Edit Your Details</h4>
</div>
<div class="card-body">
@CreateEditFormFields()
</div>
</div>
</EditForm>
}
else
{
<div class="card cw-480">
<div class="card-header text-center py-3">
<h4>Details</h4>
@* <DxButton Click="StartEditing" RenderStyle="ButtonRenderStyle.Primary">Create new</DxButton> *@
</div>
<div class="card-body">
@CreateCardView()
</div>
</div>
}
<p class="tm-8 cw-480 mt-2">
@FormSubmitResult
</p>
@code {
[Parameter] public object? Data { get; set; }
[Parameter] public List<string> IgnoreReflection { get; set; }
[Parameter] public EventCallback<object> OnSubmit { get; set; }
[Parameter] public bool isEditing { get; set; } = false;
[Parameter] public bool userAvailable { get; set; }
[Parameter] public UserModelDtoDetail userModelDtodetail { get; set; }
[Parameter] public Product CurrentProduct { get; set; }
string _formSubmitResult = "";
private string _spinnerClass = "";
string FormSubmitResult = "";
private LoggerClient<DynamicEditForm> _logger;
string PhoneMask { get; set; } = AcRegExpression.PhoneNumberMask;
string EmailMask { get; set; } = AcRegExpression.EmailMask;
protected override void OnInitialized()
{
_logger = new LoggerClient<DynamicEditForm>(LogWriters.ToArray());
base.OnInitialized();
}
protected override void OnParametersSet()
{
StateHasChanged();
base.OnParametersSet();
}
// void HandleValidSubmit()
// {
// FormSubmitResult = "You have been registered successfully.";
// isEditing = false; // Stop editing after successful submission
// }
async Task HandleValidSubmit()
{
//_spinnerClass = "spinner-border spinner-border-sm";
//await Task.Delay(500);
var debugString = "Success: ";
var myType = Data.GetType();
IList<PropertyInfo> props = new List<PropertyInfo>(myType.GetProperties());
foreach (var prop in props)
{
var propValue = prop.GetValue(Data, null);
// Do something with propValue
debugString += $"{prop.Name} = {propValue}\n";
}
_formSubmitResult = debugString;
_spinnerClass = "";
await OnSubmit.InvokeAsync(Data);
isEditing = false;
}
void HandleInvalidSubmit()
{
FormSubmitResult = "Please correct all errors";
}
void StartEditing()
{
isEditing = true;
}
public RenderFragment CreateCardView() => cardViewBuilder =>
{
var mytype = Data.GetType();
var propertyList = mytype.GetProperties();
foreach (var property in propertyList)
{
if (IgnoreReflection.Contains(property.Name))
{
continue;
}
var displayLabel = (DisplayAttribute)property.GetCustomAttributes(typeof(DisplayAttribute), false).FirstOrDefault();
cardViewBuilder.OpenElement(0, "p");
cardViewBuilder.AddContent(1, $"{displayLabel?.Name ?? property.Name}: {property.GetValue(Data)}");
cardViewBuilder.CloseElement();
}
};
public RenderFragment CreateEditFormFields() => formLayoutBuilder =>
{
_logger.Debug($"Data type: {Data.GetType().FullName}");
var mytype = Data.GetType();
var propertyList = mytype.GetProperties();
_logger.Debug($"Data property list count: {propertyList.Length}");
formLayoutBuilder.OpenComponent<DxFormLayout>(0);
formLayoutBuilder.AddAttribute(1, "ChildContent", (RenderFragment)((layoutItemBuilder) =>
{
int i = 0;
foreach (var property in propertyList)
{
if (IgnoreReflection.Contains(property.Name))
{
continue;
}
var attrList = (DataTypeAttribute)property.GetCustomAttributes(typeof(DataTypeAttribute), false).FirstOrDefault();
var displayLabel = (DisplayAttribute)property.GetCustomAttributes(typeof(DisplayAttribute), false).FirstOrDefault();
layoutItemBuilder.OpenComponent<DxFormLayoutItem>(i++);
layoutItemBuilder.AddAttribute(i++, "Caption", displayLabel?.Name ?? property.Name);
layoutItemBuilder.AddAttribute(i++, "ColSpanMd", 12);
var access = Expression.Property(Expression.Constant(Data), property.Name);
var lambda = Expression.Lambda(typeof(Func<>).MakeGenericType(property.PropertyType), access);
layoutItemBuilder.AddAttribute(i++, "Template", (RenderFragment<Object>)((context) => ((editor) =>
{
var j = 0;
switch (attrList?.DataType)
{
case DataType.Text:
editor.OpenComponent<DxTextBox>(j++);
editor.AddAttribute(j++, "Text", property.GetValue(Data));
editor.AddAttribute(j++, "TextExpression", lambda);
editor.AddAttribute(j++, "CssClass", "form-field");
editor.AddAttribute(j++, "TextChanged", EventCallback.Factory.Create<string>(this, str => { property.SetValue(Data, str); }));
editor.CloseComponent();
break;
case DataType.Password:
editor.OpenComponent<DxTextBox>(j++);
editor.AddAttribute(j++, "Password", true);
editor.AddAttribute(j++, "NullText", "Password");
editor.AddAttribute(j++, "Text", property.GetValue(Data));
editor.AddAttribute(j++, "CssClass", "form-field");
editor.AddAttribute(j++, "TextExpression", lambda);
editor.AddAttribute(j++, "TextChanged", EventCallback.Factory.Create<string>(this, str => { property.SetValue(Data, str); }));
editor.CloseComponent();
break;
case DataType.PhoneNumber:
editor.OpenComponent<DxMaskedInput<string>>(j++);
editor.AddAttribute(j++, "Value", property.GetValue(Data));
editor.AddAttribute(j++, "MaskMode", MaskMode.RegEx);
editor.AddAttribute(j++, "Mask", PhoneMask);
editor.AddAttribute(j++, "BindValueMode", BindValueMode.OnInput);
editor.AddAttribute(j++, "NullText", "+11234567890");
editor.AddAttribute(j++, "MaskAutoCompleteMode", MaskAutoCompleteMode.None);
editor.AddAttribute(j++, "ValueExpression", lambda);
editor.AddAttribute(j++, "CssClass", "form-field");
editor.AddAttribute(j++, "ValueChanged", EventCallback.Factory.Create<string>(this, str => { property.SetValue(Data, str); }));
editor.CloseComponent();
break;
case DataType.Date:
editor.OpenComponent<DxDateEdit<DateTime>>(j);
editor.AddAttribute(j++, "Date", property.GetValue(Data));
editor.AddAttribute(j++, "DateExpression", lambda);
editor.AddAttribute(j++, "CssClass", "form-field");
editor.AddAttribute(j++, "TimeSectionVisible", true);
editor.AddAttribute(j++, "TimeSectionScrollPickerFormat", "tt h m");
editor.AddAttribute(j++, "DateChanged", EventCallback.Factory.Create<DateTime>(this, str => { property.SetValue(Data, str); }));
editor.CloseComponent();
break;
case DataType.Custom:
if (property.PropertyType == typeof(double))
{
editor.OpenComponent<DxMaskedInput<double>>(j);
editor.AddAttribute(j++, "Value", property.GetValue(Data));
editor.AddAttribute(j++, "Mask", "n6");
editor.AddAttribute(j++, "BindValueMode", BindValueMode.OnInput);
editor.AddAttribute(j++, "ValueExpression", lambda);
editor.AddAttribute(j++, "CssClass", "form-field");
editor.AddAttribute(j++, "ValueChanged", EventCallback.Factory.Create<double>(this, str => { property.SetValue(Data, str); }));
editor.CloseComponent();
break;
}
else if (property.PropertyType == typeof(int))
{
editor.OpenComponent<DxMaskedInput<int>>(j);
editor.AddAttribute(j++, "Value", property.GetValue(Data));
editor.AddAttribute(j++, "BindValueMode", BindValueMode.OnInput);
editor.AddAttribute(j++, "Mask", NumericMask.WholeNumber);
editor.AddAttribute(j++, "ValueExpression", lambda);
editor.AddAttribute(j++, "CssClass", "form-field");
editor.AddAttribute(j++, "ValueChanged", EventCallback.Factory.Create<int>(this, str => { property.SetValue(Data, str); }));
editor.CloseComponent();
break;
}
else if (property.PropertyType == typeof(IEnumerable<string>) && property.Name == "Occupation")
{
editor.OpenComponent<AcComboBox<string, string>>(j);
editor.AddAttribute(j++, "Data", AdditionalData.Occupations);
editor.AddAttribute(j++, "Value", property.GetValue(Data));
editor.AddAttribute(j++, "ValueExpression", lambda);
editor.AddAttribute(j++, "ValueChanged", EventCallback.Factory.Create<string>(this, str => { property.SetValue(Data, str); }));
editor.CloseComponent();
break;
}
else if (property.PropertyType == typeof(string) && string.Compare(attrList.CustomDataType, "TransferDestination", true) == 0)
{
editor.OpenComponent<ComboboxItemSelector>(j);
editor.AddAttribute(j++, "TextValue", property.GetValue(Data));
editor.AddAttribute(j++, "CssClass", "form-field");
if (CurrentProduct != null)
{
editor.AddAttribute(j++, "ProductId", CurrentProduct.Id);
}
// editor.AddAttribute(j++, "ValExpression", lambda);
editor.AddAttribute(j++, "OnSliderChanged", EventCallback.Factory.Create<string>(this, result =>
{
_logger.Debug($"Slider changed to {result}");
property.SetValue(Data, result);
_logger.DetailConditional($"bleh: {property.Name} = {property.GetValue(Data)}");
}));
editor.CloseComponent();
}
else if (property.PropertyType == typeof(string) && string.Compare(attrList.CustomDataType, "FullName", true) == 0)
{
editor.OpenComponent<FullNameEditor>(j);
editor.AddAttribute(j++, "NullText", "");
editor.AddAttribute(j++, "FirstNameChanged", EventCallback.Factory.Create<string>(this, result =>
{
_logger.DetailConditional($"FirstName changed to {result}");
//find property with name FirstName
var firstNameProperty = propertyList.FirstOrDefault(p => p.Name == "FirstName");
firstNameProperty.SetValue(Data, result);
//find property with name LastName
var lastNameProperty = propertyList.FirstOrDefault(p => p.Name == "LastName");
//combine the two values, if they are not null
if (firstNameProperty != null && lastNameProperty != null)
{
var firstName = result;
var lastName = (string)lastNameProperty.GetValue(Data);
var fullName = $"{firstName} {lastName}";
property.SetValue(Data, fullName);
}
}));
editor.AddAttribute(j++, "LastNameChanged", EventCallback.Factory.Create<string>(this, result =>
{
_logger.DetailConditional($"LastName changed to {result}");
//find property with name FirstName
var firstNameProperty = propertyList.FirstOrDefault(p => p.Name == "FirstName");
//find property with name LastName
var lastNameProperty = propertyList.FirstOrDefault(p => p.Name == "LastName");
lastNameProperty.SetValue(Data, result);
//combine the two values, if they are not null
if (firstNameProperty != null && lastNameProperty != null)
{
var firstName = (string)firstNameProperty.GetValue(Data);
var lastName = result;
var fullName = $"{firstName} {lastName}";
property.SetValue(Data, fullName);
}
_logger.DetailConditional($"bleh: {property.Name} = {property.GetValue(Data)}");
StateHasChanged(); // Add this line to refresh the UI
}));
editor.CloseComponent();
editor.OpenComponent<DxTextBox>(j++);
/*editor.AddAttribute(j++, "CssClass", "form-field");*/
editor.AddAttribute(j++, "NullText", "Please type in the above fields");
editor.AddAttribute(j++, "Enabled", false);
editor.AddAttribute(j++, "Text", property.GetValue(Data));
editor.AddAttribute(j++, "TextExpression", lambda);
editor.AddAttribute(j++, "TextChanged", EventCallback.Factory.Create<string>(this, str =>
{
property.SetValue(Data, str);
_logger.DetailConditional($"bleh: {property.Name} = {property.GetValue(Data)}");
}));
editor.CloseComponent();
}
break;
case DataType.MultilineText:
editor.OpenComponent<DxMemo>(j);
editor.AddAttribute(j++, "Text", property.GetValue(Data));
editor.AddAttribute(j++, "CssClass", "form-field");
editor.AddAttribute(j++, "TextExpression", lambda);
editor.AddAttribute(j++, "TextChanged", EventCallback.Factory.Create<string>(this, str => { property.SetValue(Data, str); }));
editor.CloseComponent();
break;
default:
editor.OpenComponent<DxTextBox>(j++);
editor.AddAttribute(j++, "Text", property.GetValue(Data));
editor.AddAttribute(j++, "CssClass", "form-field");
editor.AddAttribute(j++, "TextExpression", lambda);
editor.AddAttribute(j++, "TextChanged", EventCallback.Factory.Create<string>(this, str => { property.SetValue(Data, str); }));
editor.CloseComponent();
break;
}
})));
layoutItemBuilder.CloseComponent();
layoutItemBuilder.OpenElement(i++, "div");
layoutItemBuilder.AddAttribute(i++, "class", "text-danger");
layoutItemBuilder.OpenComponent(i++, typeof(ValidationMessage<>).MakeGenericType(property.PropertyType));
layoutItemBuilder.AddAttribute(i++, "For", lambda);
layoutItemBuilder.CloseComponent();
layoutItemBuilder.CloseElement();
}
layoutItemBuilder.OpenComponent<DxFormLayoutItem>(i++);
layoutItemBuilder.AddAttribute(i++, "Template", (RenderFragment<Object>)((context) => ((editor) =>
{
editor.OpenComponent<DxButton>(i++);
editor.AddAttribute(i++, "SubmitFormOnClick", true);
editor.AddAttribute(i++, "Text", "Save");
editor.CloseComponent();
})));
layoutItemBuilder.CloseComponent();
}));
formLayoutBuilder.CloseComponent();
};
}