public static IEnumerable <CrudeProperty> ParseProperties(object viewModel) { var items = new List <CrudeProperty>(); var properties = viewModel.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance); var methods = ParseMethods(viewModel); foreach (var property in properties) { var attributes = property.GetCustomAttributes(typeof(CrudePropertyAttribute)).ToList(); if (attributes.Any(x => x is CrudeIgnoreAttribute)) { continue; } var order = int.MaxValue; if (attributes.FirstOrDefault(x => x is CrudeOrderAttribute) is CrudeOrderAttribute orderAttribute) { order = orderAttribute.Order; } var name = property.Name; if (property.GetCustomAttributes(typeof(DisplayAttribute)).FirstOrDefault(x => x is DisplayAttribute) is DisplayAttribute displayAttribute) { var displayName = displayAttribute.GetName(); if (displayName != null) { name = displayName; } } var disabled = attributes.FirstOrDefault(x => x is CrudeDisableAttribute) is CrudeDisableAttribute _; var password = attributes.FirstOrDefault(x => x is CrudePasswordAttribute) is CrudePasswordAttribute _; CrudeEvent?onClick = null; foreach (var method in methods) { if (method.Attributes.FirstOrDefault(x => x is CrudeOnClickAttribute) is CrudeOnClickAttribute onClickAttribute) { if (onClickAttribute.Property == property.Name) { onClick = new CrudeEvent(() => method.MethodInfo.Invoke(viewModel, Array.Empty <object>())); } } } items.Add(new CrudeProperty(name, order, onClick, property, viewModel, disabled, password)); } return(items.OrderBy(x => x.Order)); }
public RenderFragment Render(RenderContext context) => builder => { var seq = 0; builder.OpenElement(seq++, "crude-table-fragment"); if (_table.IsSearchable) { builder.OpenElement(seq++, "crude-table-fragment-header"); BuildSearchBox(ref seq, context, builder); builder.CloseElement(); } builder.OpenElement(seq++, "table"); builder.OpenElement(seq++, "thead"); builder.OpenElement(seq++, "tr"); var headerInstance = Activator.CreateInstance(typeof(T)); if (headerInstance == null) { throw new ArgumentException($"Failed to construct table headers for type {typeof(T)}. Make sure you have an empty constructor"); } var items = ViewModelParser.ParseProperties(headerInstance); foreach (var item in items) { builder.OpenElement(seq++, "th"); CrudeEvent?sortEvent = null; if (_table.IsSortable) { sortEvent = new CrudeEvent(() => { if (_table.SortColumn == item.Info.Name) { _table.SortDescending = !_table.SortDescending; } else { _table.SortColumn = item.Info.Name; _table.SortDescending = false; } }); } var header = new ActionDecoratorFragment(item.Name, sortEvent); builder.AddContent(seq++, header.Render(context)); if (item.Info.Name == _table.SortColumn) { builder.OpenElement(seq++, "crude-table-sort-icon"); builder.AddAttribute(seq++, "class", _table.SortDescending ? "sort-desc" : "sort-asc"); builder.CloseElement(); } builder.CloseElement(); } builder.CloseElement(); builder.CloseElement(); builder.OpenElement(seq++, "tbody"); var elements = _table.GetElements(); foreach (var element in elements) { builder.OpenElement(seq++, "tr"); var rowItems = ViewModelParser.ParseProperties(element); foreach (var item in rowItems) { builder.OpenElement(seq++, "td"); builder.AddContent(seq++, GetValue(item, context)); builder.CloseElement(); } builder.CloseElement(); } builder.CloseElement(); builder.CloseElement(); var elementCount = _table.GetTotalElementCount(); if (elementCount > _table.TablePageSize) { builder.OpenElement(seq++, "crude-table-fragment-footer"); BuildPaginationButtons(ref seq, elementCount, context, builder); builder.CloseElement(); } builder.CloseElement(); };