Files
Moonlight/Moonlight/Shared/Components/Forms/AutoProperty.razor

151 lines
4.9 KiB
Plaintext

@using System.Reflection
@using System.ComponentModel
@using Microsoft.AspNetCore.Components.Forms
@using Moonlight.App.Extensions.Attributes
@using Moonlight.App.Repositories
@typeparam TProp
@inject IServiceProvider ServiceProvider
<label class="form-label">
@(Formatter.ConvertCamelCaseToSpaces(Property.Name))
</label>
@* Description using attribute *@
@{
var attrs = Property.GetCustomAttributes(true);
var descAttr = attrs
.FirstOrDefault(x => x.GetType() == typeof(DescriptionAttribute));
}
@if (descAttr != null)
{
var attribute = descAttr as DescriptionAttribute;
<div class="form-text fs-5 mb-2 mt-0">
@(attribute!.Description)
</div>
}
@* Actual value binding *@
<div class="input-group mb-5">
@if (Property.PropertyType == typeof(string))
{
<div class="w-100">
<InputText id="@Property.Name" @bind-Value="Binder.StringValue" class="form-control"/>
</div>
}
else if (Property.PropertyType == typeof(int))
{
<InputNumber id="@Property.Name" @bind-Value="Binder.IntValue" class="form-control"/>
}
else if (Property.PropertyType == typeof(double))
{
<InputNumber id="@Property.Name" @bind-Value="Binder.DoubleValue" class="form-control"/>
}
else if (Property.PropertyType == typeof(long))
{
<InputNumber id="@Property.Name" @bind-Value="Binder.LongValue" class="form-control"/>
}
else if (Property.PropertyType == typeof(bool))
{
<div class="form-check">
<InputCheckbox id="@Property.Name" @bind-Value="Binder.BoolValue" class="form-check-input"/>
</div>
}
else if (Property.PropertyType == typeof(DateTime))
{
<InputDate id="@Property.Name" @bind-Value="Binder.DateTimeValue" class="form-control"/>
}
else if (Property.PropertyType == typeof(decimal))
{
<InputNumber id="@Property.Name" step="0.01" @bind-Value="Binder.DoubleValue" class="form-control"/>
}
else if (Property.PropertyType.IsEnum)
{
<select @bind="Binder.Class" class="form-select">
@foreach (var status in (TProp[])Enum.GetValues(typeof(TProp)))
{
if (Binder.Class.ToString() == status.ToString())
{
<option value="@(status)" selected="">@(status)</option>
}
else
{
<option value="@(status)">@(status)</option>
}
}
</select>
}
else if (Property.PropertyType.IsClass)
{
var attribute = Property.GetCustomAttributes(true)
.FirstOrDefault(x => x.GetType() == typeof(SelectorAttribute)) as SelectorAttribute;
if (attribute != null)
{
if (attribute.UseDropdown)
{
var displayFunc = new Func<TProp, string>(x =>
{
var prop = typeof(TProp).GetProperties().First(x => x.Name == attribute.DisplayProp);
return prop.GetValue(x) as string ?? "N/A";
});
var searchFunc = new Func<TProp, string>(x =>
{
var prop = typeof(TProp).GetProperties().First(x => x.Name == attribute.SelectorProp);
return prop.GetValue(x) as string ?? "N/A";
});
<SmartDropdown @bind-Value="Binder.Class" DisplayFunc="displayFunc" SearchProp="searchFunc" Items="Items" />
}
else
{
var displayFunc = new Func<TProp, string>(x =>
{
var prop = typeof(TProp).GetProperties().First(x => x.Name == attribute.DisplayProp);
return prop.GetValue(x) as string ?? "N/A";
});
<SmartSelect @bind-Value="Binder.Class" DisplayField="displayFunc" Items="Items" CanBeNull="true" />
}
}
}
</div>
@code
{
[CascadingParameter(Name = "Data")]
public object Data { get; set; }
[CascadingParameter(Name = "Property")]
public PropertyInfo Property { get; set; }
private PropBinder<TProp> Binder;
private TProp[] Items = Array.Empty<TProp>();
protected override void OnInitialized()
{
Binder = new(Property, Data);
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
if (Property.GetCustomAttributes(true).Any(x => x.GetType() == typeof(SelectorAttribute)))
{
var typeToGetByDi = typeof(Repository<>).MakeGenericType(typeof(TProp));
var repo = ServiceProvider.GetRequiredService(typeToGetByDi);
var dbSet = repo.GetType().GetMethods().First(x => x.Name == "Get").Invoke(repo, null) as IEnumerable<TProp>;
Items = dbSet!.ToArray();
await InvokeAsync(StateHasChanged);
}
}
}
}