292 lines
12 KiB
Plaintext
292 lines
12 KiB
Plaintext
|
|
@using System.Linq.Expressions
|
|
@using System.ComponentModel.DataAnnotations
|
|
@using System.Reflection
|
|
@using Microsoft.AspNetCore.Components.Rendering
|
|
|
|
@if (isEditing)
|
|
{
|
|
<EditForm Model="@Data"
|
|
OnValidSubmit="@HandleValidSubmit"
|
|
OnInvalidSubmit="@HandleInvalidSubmit"
|
|
Context="EditFormContext">
|
|
<DataAnnotationsValidator />
|
|
<div class="card">
|
|
<div class="card-header text-center py-3">
|
|
<h4>@TitleString</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; } =new();
|
|
[Parameter] public EventCallback<object> OnSubmit { get; set; }
|
|
[Parameter] public bool isEditing { get; set; } = false;
|
|
[Parameter] public string TitleString { get; set; } = "Edit your details";
|
|
[Parameter] public string ButtonTextString { get; set; } = "Submit";
|
|
|
|
string _formSubmitResult = "";
|
|
private string _spinnerClass = "";
|
|
|
|
string FormSubmitResult = "";
|
|
string PhoneMask { get; set; } = @"((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?";
|
|
string EmailMask { get; set; } = @"\+(9[976]\d|8[987530]\d|6[987]\d|5[90]\d|42\d|3[875]\d|2[98654321]\d|9[8543210]|8[6421]|6[6543210]|5[87654321]|4[987654310]|3[9643210]|2[70]|7|1)\W*\d(\W*\d){1,14}";
|
|
|
|
protected override void OnInitialized()
|
|
{
|
|
base.OnInitialized();
|
|
}
|
|
|
|
protected override void OnParametersSet()
|
|
{
|
|
StateHasChanged();
|
|
base.OnParametersSet();
|
|
}
|
|
|
|
|
|
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 =>
|
|
{
|
|
var modelType = Data.GetType();
|
|
var properties = modelType.GetProperties();
|
|
|
|
formLayoutBuilder.OpenComponent<EditForm>(0);
|
|
formLayoutBuilder.AddAttribute(1, "Model", Data);
|
|
formLayoutBuilder.AddAttribute(2, "ChildContent", (RenderFragment<EditContext>)((editContext) => (builder) =>
|
|
{
|
|
int seq = 0;
|
|
foreach (var property in properties)
|
|
{
|
|
if (IgnoreReflection.Contains(property.Name))
|
|
continue;
|
|
|
|
var dataTypeAttr = (DataTypeAttribute)property.GetCustomAttributes(typeof(DataTypeAttribute), false).FirstOrDefault();
|
|
var displayAttr = (DisplayAttribute)property.GetCustomAttributes(typeof(DisplayAttribute), false).FirstOrDefault();
|
|
|
|
var displayName = displayAttr?.Name ?? property.Name;
|
|
|
|
var propertyAccess = Expression.Property(Expression.Constant(Data), property.Name);
|
|
var lambda = Expression.Lambda(
|
|
typeof(Func<>).MakeGenericType(property.PropertyType),
|
|
propertyAccess
|
|
);
|
|
|
|
// Label
|
|
builder.OpenElement(seq++, "div");
|
|
builder.AddContent(seq++, displayName);
|
|
|
|
// Input control
|
|
builder.OpenElement(seq++, "div");
|
|
|
|
if (property.PropertyType == typeof(string))
|
|
{
|
|
if (dataTypeAttr?.DataType == DataType.MultilineText)
|
|
{
|
|
builder.OpenComponent<InputTextArea>(seq++);
|
|
builder.AddAttribute(seq++, "Value", (string?)property.GetValue(Data));
|
|
builder.AddAttribute(seq++, "ValueChanged", EventCallback.Factory.Create<string>(this, val => property.SetValue(Data, val)));
|
|
builder.AddAttribute(seq++, "ValueExpression", lambda);
|
|
builder.CloseComponent();
|
|
}
|
|
else
|
|
{
|
|
builder.OpenComponent<InputText>(seq++);
|
|
builder.AddAttribute(seq++, "Value", (string?)property.GetValue(Data));
|
|
builder.AddAttribute(seq++, "ValueChanged", EventCallback.Factory.Create<string>(this, val => property.SetValue(Data, val)));
|
|
builder.AddAttribute(seq++, "ValueExpression", lambda);
|
|
builder.CloseComponent();
|
|
}
|
|
}
|
|
else if (property.PropertyType == typeof(int))
|
|
{
|
|
builder.OpenComponent<InputNumber<int>>(seq++);
|
|
builder.AddAttribute(seq++, "Value", (int?)property.GetValue(Data));
|
|
builder.AddAttribute(seq++, "ValueChanged", EventCallback.Factory.Create<int>(this, val => property.SetValue(Data, val)));
|
|
builder.AddAttribute(seq++, "ValueExpression", lambda);
|
|
builder.CloseComponent();
|
|
}
|
|
else if (property.PropertyType == typeof(double))
|
|
{
|
|
builder.OpenComponent<InputNumber<double>>(seq++);
|
|
builder.AddAttribute(seq++, "Value", (double?)property.GetValue(Data));
|
|
builder.AddAttribute(seq++, "ValueChanged", EventCallback.Factory.Create<double>(this, val => property.SetValue(Data, val)));
|
|
builder.AddAttribute(seq++, "ValueExpression", lambda);
|
|
builder.CloseComponent();
|
|
}
|
|
else if (property.PropertyType == typeof(DateOnly))
|
|
{
|
|
builder.OpenComponent<InputDate<DateOnly>>(seq++);
|
|
builder.AddAttribute(seq++, "Value", (DateOnly?)property.GetValue(Data));
|
|
builder.AddAttribute(seq++, "ValueChanged", EventCallback.Factory.Create<DateOnly>(this, val => property.SetValue(Data, val)));
|
|
builder.AddAttribute(seq++, "ValueExpression", lambda);
|
|
builder.CloseComponent();
|
|
}
|
|
|
|
builder.CloseElement(); // end of input wrapper
|
|
|
|
// Validation message
|
|
builder.OpenComponent(seq++, typeof(ValidationMessage<>).MakeGenericType(property.PropertyType));
|
|
builder.AddAttribute(seq++, "For", lambda);
|
|
builder.CloseComponent();
|
|
|
|
builder.CloseElement(); // end of outer div
|
|
}
|
|
|
|
// Submit button
|
|
builder.OpenElement(seq++, "button");
|
|
builder.AddAttribute(seq++, "type", "submit");
|
|
builder.AddContent(seq++, ButtonTextString ?? "Submit");
|
|
builder.CloseElement();
|
|
}));
|
|
formLayoutBuilder.CloseComponent();
|
|
};
|
|
|
|
|
|
private void RenderInputComponent(RenderTreeBuilder builder, ref int seq, PropertyInfo prop, DataTypeAttribute? typeAttr, object? value, LambdaExpression lambda)
|
|
{
|
|
var type = typeAttr?.DataType ?? DataType.Text;
|
|
|
|
switch (type)
|
|
{
|
|
case DataType.Password:
|
|
builder.OpenComponent<InputText>(seq++);
|
|
builder.AddAttribute(seq++, "type", "password");
|
|
builder.AddAttribute(seq++, "Value", value);
|
|
builder.AddAttribute(seq++, "ValueChanged", EventCallback.Factory.Create<string>(this, v => prop.SetValue(Data, v)));
|
|
builder.AddAttribute(seq++, "ValueExpression", lambda);
|
|
builder.CloseComponent();
|
|
break;
|
|
|
|
case DataType.PhoneNumber:
|
|
builder.OpenComponent<InputText>(seq++);
|
|
builder.AddAttribute(seq++, "Value", value);
|
|
builder.AddAttribute(seq++, "ValueChanged", EventCallback.Factory.Create<string>(this, v => prop.SetValue(Data, v)));
|
|
builder.AddAttribute(seq++, "ValueExpression", lambda);
|
|
builder.AddAttribute(seq++, "Placeholder", "+11234567890");
|
|
builder.CloseComponent();
|
|
break;
|
|
|
|
case DataType.Date:
|
|
builder.OpenComponent<InputDate<DateOnly>>(seq++);
|
|
builder.AddAttribute(seq++, "Value", value);
|
|
builder.AddAttribute(seq++, "ValueChanged", EventCallback.Factory.Create<DateOnly>(this, v => prop.SetValue(Data, v)));
|
|
builder.AddAttribute(seq++, "ValueExpression", lambda);
|
|
builder.CloseComponent();
|
|
break;
|
|
|
|
case DataType.MultilineText:
|
|
builder.OpenComponent<InputTextArea>(seq++);
|
|
builder.AddAttribute(seq++, "Value", value);
|
|
builder.AddAttribute(seq++, "ValueChanged", EventCallback.Factory.Create<string>(this, v => prop.SetValue(Data, v)));
|
|
builder.AddAttribute(seq++, "ValueExpression", lambda);
|
|
builder.CloseComponent();
|
|
break;
|
|
|
|
case DataType.Custom:
|
|
if (prop.PropertyType == typeof(double))
|
|
{
|
|
builder.OpenComponent<InputNumber<double>>(seq++);
|
|
builder.AddAttribute(seq++, "Value", value);
|
|
builder.AddAttribute(seq++, "ValueChanged", EventCallback.Factory.Create<double>(this, v => prop.SetValue(Data, v)));
|
|
builder.AddAttribute(seq++, "ValueExpression", lambda);
|
|
builder.CloseComponent();
|
|
}
|
|
else if (prop.PropertyType == typeof(int))
|
|
{
|
|
builder.OpenComponent<InputNumber<int>>(seq++);
|
|
builder.AddAttribute(seq++, "Value", value);
|
|
builder.AddAttribute(seq++, "ValueChanged", EventCallback.Factory.Create<int>(this, v => prop.SetValue(Data, v)));
|
|
builder.AddAttribute(seq++, "ValueExpression", lambda);
|
|
builder.CloseComponent();
|
|
}
|
|
break;
|
|
|
|
default:
|
|
builder.OpenComponent<InputText>(seq++);
|
|
builder.AddAttribute(seq++, "Value", value);
|
|
builder.AddAttribute(seq++, "ValueChanged", EventCallback.Factory.Create<string>(this, v => prop.SetValue(Data, v)));
|
|
builder.AddAttribute(seq++, "ValueExpression", lambda);
|
|
builder.CloseComponent();
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
|