KorzhCom / EasyData

Adaptive CRUD for ASP.NET Core. With EasyData you can get both API endpoints and client-side UI for all CRUD operations in a matter of minutes using just your DbContext and a few lines of code.
MIT License
594 stars 63 forks source link

Filter for One entity CRUD page #118

Closed sanket-pattekar closed 2 years ago

sanket-pattekar commented 2 years ago

Hi

I am using the One entity CRUD page. Is there a way to filter (sql where clause ) the records that are displayed. I do not want to show the entire table but a sub-set of rows that match the criteria

Sanket

korzh commented 2 years ago

Hello,

It's possible to do in general but it would not be quite easy. Here are the steps:

  1. Create your own filter class derived from EasyFilter and define the filtering logic there.
  2. Define a custom EasyDataManager derived from EasyDataManagerEF
  3. Override its FetchDatasetAsync method. Add your own filter to the list of filters and pass the new list to the base procedure.
  4. Register your custom manager in EasyData middleware with options.UseManager<>() call.

Here is the code:

    public class CustomEasyDataManager : EasyDataManagerEF<AppDbContext>
    {
        public CustomEasyDataManager(IServiceProvider services, EasyDataOptions options) 
            : base(services, options)
        {
        }

        public override async Task<EasyDataResultSet> FetchDatasetAsync(
                string modelId,
                string sourceId,
                IEnumerable<EasyFilter> filters = null,
                IEnumerable<EasySorter> sorters = null,
                bool isLookup = false, int? offset = null, int? fetch = null, CancellationToken ct = default)
        { 

            var myFilters = new List<EasyFilter>(filters);
            myFilters.Add(new MyCustomFilter());

            return await base.FetchDatasetAsync(modelId, sourceId, myFilters, sorters, isLookup, offset, fetch, ct);
        }
    }

    public class MyCustomFilter : EasyFilter
    {
        public MyCustomFilter(MetaData model) : base(model)
        {
        }

        public override object Apply(MetaEntity entity, bool isLookup, object data)
        {
            if (entity.Name != "Order") return data;

            return GetType().GetMethods(BindingFlags.Instance | BindingFlags.NonPublic)
               .Single(m => m.Name == "FilterQueryable" && m.IsGenericMethodDefinition)
               .MakeGenericMethod(entity.ClrType)
               .Invoke(this, new object[] { entity, isLookup, data });
        }

        private IQueryable<T> FilterQueryable<T>(MetaEntity entity, bool isLookup, object data) where T : class
        {
            var query = (IQueryable<T>)data;
            return query.Where(/* your condition is here */);
        }

        public override Task ReadFromJsonAsync(JsonReader reader, CancellationToken ct = default)
        {
            //do nothing since  we will not read the parameters of this filter from a request
            return Task.CompletedTask;
        }
    }

And here is the registration of the custom manager in the middleware:

    endpoints.MapEasyData((options) => {
        options.UseManager<CustomEasyDataManager>();
        .     .    .    .
    });
sanket-pattekar commented 2 years ago

Tried the solution and it works. However for my requirement, the filter condition is dynamic and is decided at runtime. Hence any solution should be at the time I invoke the javascript and not in the c# code

var dispatcher = new easydata.crud.EasyDataViewDispatcher({
                    basePath: '/masterdata',
                    endpoint: '/api/masterdata',
                    rootEntity: tableName,
           filter: <where clause>,
                }).run();
korzh commented 2 years ago

A possibility to define client-side filters in EasyData is planned but not implemented yet. We have a basic implementation for this feature under the hood and we have one filter (substring) already implemented now. However, it's not possible to define any custom filter for the entity yet.

If you need dynamic queries functionality in general we have another product for that: EasyQuery

It's based on EasyData and adds a lot of extra features like data filtering (with a friendly UI), ad-hoc reporting, more capabilities for data visualization, grouping/aggregation, and much more. However, it's a commercial product.

antifree commented 2 years ago

I'll close due to inactivity