Git Product home page Git Product logo

Comments (11)

shlomiassaf avatar shlomiassaf commented on August 26, 2024 1

Hi,

To set a filter you can use the setFilter method in PblDataSource:

  setFilter(value: DataSourceFilterToken, columns: PblColumn[]): void;

The token can be:

export type DataSourceFilterToken = undefined | DataSourcePredicate | any;

With any being a value to compare to, which will automatically compare the values in the columns provided into the value you provided to the filter.

For a more fine-grained control, you can use DataSourcePredicate

export type DataSourcePredicate = (item: any, properties: PblColumn[]) => boolean;

The predicate function will get the item which is the row and the list of columns to filter by.

You can use PblColumn.getValue(item) to get the actual value of each column for the provided row (item).

You can see how the internal implementation handles this, when the filter is a value and not a predicate here


There is another way to filter, by instruction the datasource to skip handling the filter functionality and so it can be passed to the datasource trigger handler, with the factory it should look like this:

const dsCustomTrigger = createDS<Person>()
  .setCustomTriggers('filter')
  .onTrigger( event => {
    if (event.filter.changed) {
      const filter = event.filter.curr; // <- Current filter, type: DataSourceFilter
      /* HANDLE FILTER CHANGES HERE IT */
    }
 
  })
  .create();

You can set more custom trigger, the full list is .setCustomTriggers('filter', 'pagination', 'sort')

This type of handling filters is more suitable when the filter/sort/pagination is handled at the server-side and not for actually handling client side filtering, for that I suggest using the predicated.

However, If you want to read more about the triggers, you can find info here. The event object can tell you the source of the trigger, which is one of: sort, pagination, filter, refresh() call or the initial call to get data.


With that being said, I do thing that the filter & sort API should get some API re-work to improve how users use them...


from ngrid.

tsiegleauq avatar tsiegleauq commented on August 26, 2024

@shlomiassaf thanks for your information! I will try that out later.

There was one more thing I noticed after playing around with setFilter.
Apparently, it is not easily possible to get the result of a filter operation, but I guess I am just missing something.

MatTableDataSource was able to use filteredData(), returning

The filtered set of data that has been matched by the filter string, or all the data if there is no filter

So, after using applyFilter(), how to get the filtered data?
PblDataSource.filter() as well as the corresponding behavior subject only return the filter types, the parent class DataSource from CDK is abstract does not implement any functions :-/

from ngrid.

shlomiassaf avatar shlomiassaf commented on August 26, 2024

@tsiegleauq I'm afraid that currently it's not possible using the built-in implementation.

I'll explain:


The entire datasource is built out of 2 units.

  • PblDataSource
  • PblDataSourceAdapter

The datasource (PblDataSource) require an adapter (PblDataSourceAdapter) to work. The datasource is just a container and the adapter does all the logical work, including calling the handler provided by the user to fetch data.

This way it's easy for the user to work with data, just use the factory function (createDS) and return an Array / Promise / Observable.

The adapter has to take care of 4 triggers:

  • Filtering
  • Sorting
  • Paging
  • Refresh

The library comes with a built in adapter that know's how to handle all of the triggers for the client side scenario, e.g. filtering on the current source, sorting on it, etc...

The factory createDS is just a helper that abstract the process of creating a new datasource and new adapter, it bind the built-in adapter with the datasource.

The built-in adapter is smart enough to allow manually handling of the triggers. For example, if you want to sort on the server side the adapter will skip that trigger and let the user manually handle it in the handler he provides.

One can always implement his own adapter, for example, if a server implements the OData protocol, such an adapter can be built which will convert all filters, sorting and pagination based on that.


Now, about your question, you refer to filtering but it might also relate to the sorted result etc...

From the adapter's perspective there might not be a filtered result, if the user has chosen to manually handle that trigger.

In addition, if the filtered result is saved and sort is also set, is it saved with sorting? and vice versa does sorted results get saved with or without filtering?

If both filtering and sorting are set it requires re-running them, but now if just filtering is changed should we cache the previous sorting and run the filtering on it or run the sort and filter again?

And what about performance? saving the sorted results, filtered results and all of the results of a 100,000 rows dataset, isn't it an issue?

With large datasets this has a huge impact.

I'm not ruling this out, just trying to think what's the best approach here.

BTW, you can always set a manually trigger on the filter and run applyFilter on the sport within the trigger handler

from ngrid.

tsiegleauq avatar tsiegleauq commented on August 26, 2024

I see. Well, displaying sorted and filtered data in a table is nice to have, but I suppose getting the filtered (and sorted) data (in code) is a pretty common use case.

A relatable way could be to use the table component to get the rusult of the sorting and filtering. Perhaps something like a "rowAPI" similar to the column API could be required.

Do you have a suggestion to tackle this?

from ngrid.

shlomiassaf avatar shlomiassaf commented on August 26, 2024

I have the sorted data already store in the adapter and I could probably store the filtered data as well...

If both sort and filter are applied the filtered data will be sorted as well, filtering comes after sort.

The question is, will it cause a performance issue if the dataset is large? a 100k rows dataset with sort is now 200k, add in a filter that has O(N) of 200k you get to 3 arrays of 300k rows (ofcourse all objects are shared but still)

The reason I store the sort results is to support fast filtering without re-sorting on each filter hit... Filtering might be time consuming, depending on implementation, and it might happen rapidly (keyboard typing) so I want to cache what I can.

Perhaps we can support an API that will emit the result of filter and sort so users can hook into them if they wish... of course this will require the emission of cloned arrays... but I can live with that.

Thoughts?

from ngrid.

tsiegleauq avatar tsiegleauq commented on August 26, 2024

There are pros and cons to ever solution. If you filter before sorting, your N will be smaller, but sorting then needs to happen again, after the filter changed.

To implement fast filtering with keyboard typing, some rxjs magic to add a "debounce time" before filtering should do the trick.

from ngrid.

turokg avatar turokg commented on August 26, 2024

@shlomiassaf, thank you for a great work, it's a fantastic package!

i have a set of filters which i need to implement:
-two columns by input text
-another by mat list selection (if column value is in selection list)
-another may be by datepicker (if columns value is in selected period)

i guess it could be done by using filterPredicate, however i really struggle with implementing this solution. Is there any example I could find?
thanks in advance!

from ngrid.

shlomiassaf avatar shlomiassaf commented on August 26, 2024

@ek2dev

You will have to use the filter predicate for this.

The filtering predicate returns a boolean value true/false given the row and columns.

Notice the input, its the row not the value of a cell.... the columns are those you set to filter by and with each column/row pair can yield the value which with you can filter.

Now, because the filter returns a predicate you can return true on the first result hit, if no hit then try searching again with the next value from the next component (e.g. mat-select) and so on until no more things to search by exist. This will be an "OR" like search, you can do an "AND" search as well.. you choose the logic.

For example, I have an input box and a selection box stored in the params inputValue and selectedValue on the component class.

Every time the input or select change the values are updated and I can react to the change.

The filter API is not perfect, it works fine for the basic usage, providing a value and filtering by it.

It requires some work for custom predicates, for example, now it not straight forward to run the filter again, unless you provide a new filter predicate which is not the right approach.

I will fix this and post a message here with an example, once done.

from ngrid.

shlomiassaf avatar shlomiassaf commented on August 26, 2024

@ek2dev Now in 1.0.0-alpha.16

See example here

from ngrid.

turokg avatar turokg commented on August 26, 2024

that worked.

thanks a lot!

from ngrid.

shlomiassaf avatar shlomiassaf commented on August 26, 2024

Fully implemented, read Features -> Column -> Column Filters page for more information.

from ngrid.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.