How to get an filtered item or get a list of all items from a table?

I’m trying to modify rows of a table when the table has a filter applied and the row is not currently being shown to the user (ie it does not pass the filter).
It seems most of the methods, like getItem() getContainerProperty() getAllItems() etc on the table/indexedContainer do not return items that are filtered.
The indexedcontainer has getUnfilteredItem and getAllItemIds() but they are protected and the docs warn that they may be removed.

What is the correct way to modify table rows that are currently hidden by a filter?
We are using it to update a table and then push the changes to the browser using Icepush addon. It’s important that when they change the filter, the updated rows are shown.

Thanks, Tom

I fear I have no solution for this, but this echoes my remarks in the
Bug in the Five Minutes Tutorial
thread. No answers so far…

If you do need to do this with IndexedContainer, you can subclass the container and make getUnfilteredItem() public or otherwise accessible to your application.

The container is not interested in property value changes and the Table component is listening for changes to properties in the view (or in the scroll buffer) but reloads items from the container when changing filters.

Then again, using another container (perhaps a custom one) would also be a good option in many cases.

Hi Henri,
Thanks for the response. Subclassing the container is exactly what I have done. This seems a little hopeful long term given the methods I am subclassing are documented as ‘for internal use only’.

Even if writing a custom container, you would surely want to subclass either IndexContainer or AbstractInMemoryContainer, and use the getUnfilteredItem() method.

I’m not sure what you mean by “The container is not interested in property value changes”. Surely in order to display any changes to the end user, it should be interested in property value changes? At the moment, it appears the interface support fetching changes (ie from a database with SQLcontainer), but not easily for pushing changes.

Personally, I think getUnfilteredItem() and other methods for accessing all the items in the container should be made public so that we can use them with confidence.

Thanks,
Tom

As I wrote above, the container has no interest in such changes (in general) - it only cares about added or removed items, and the values handled by the items and their properties. It is the display component (e.g. Table) that cares about property value changes. Some specific containers may choose to listen to property change events as well for various reasons.

[quote]
Even if writing a custom container, you would surely want to subclass either IndexContainer or AbstractInMemoryContainer, and use the getUnfilteredItem() method.

It should not be public as it is logically internal API and normally not meant to be used from outside the container, at least for most in-memory containers. If a specific container does want to expose it (or another API on top of it), it can.

If I remember correctly, it is actually the only method you have to implement for a very minimal and restricted subclass of AbstractInMemoryContainer. You need not worry too much about it disappearing.

I’ve run into the same scenario as Tom Howe, and I also think the AbstractInMemoryContainer (or maybe Container.Filterable) should have methods that expose the entirety of items it maintains.

Right now (as of 6.7.1) it only exposes visible items, but this leads to some pretty counterintuitive behavior.

For example:

Table table; // Uses an IndexedContainer (subclass of AbstractInMemoryContainer)
Object myRowObject;
Item myItem = table.addItem(myRowObject);
table.containsId(myRowObject); // true, naturally
// ... some filter operation occurs, hiding myItem ...
table.containsId(myRowObject); // false (ok, I can buy that, it's hidden)
// now, two examples of where it gets weird:
Item myNewItem = table.addItem(myRowObject); // myNewItem is null. addItem fails, because myRowObject is still in there somewhere (albeit filtered out)
// or:
table.removeItem(myRowObject); // true (it can be successfully removed, even though containsId just told me the item wasn't there).

I certainly wouldn’t argue that any existing behavior would change on AbstractInMemoryContainer, but I think anything doing filtering should also make its full, unfiltered list of items available. The call above to “containsId” would instead become something like table.containsId(myRowObject, true), specifying whether to include items that are filtered out.

In case it’s not clear, here’s the scenario where this functionality is desired:

  1. Container-based component displays full list of 10 items.
  2. Filter operation occurs. Let’s say only rows 1-5 are visible now.
  3. Due to a separate event in the application, some attribute of the object from, say, row 7 (now hidden) changes.
  4. Knowing about this change, the application attempts to find item 7 in the component in order to update its display properties, in the event that the filtering conditions change and it becomes visible again.

I see three workarounds until/unless the full, unfiltered list is accessible:
A) Subclass AbstractInMemoryContainer in order to make a public version of getAllItemIds.
Like Tom, I am also a bit uncomfortable accessing a protected method (getAllItemIds) specifically marked “Avoid using this method outside this class, may disappear in future versions.”
B ) Maintain a full list of Items outside of the Container.
C) Rather than checking to see if the container contains an item via containsId, blindly remove the item (if it exists) with the given itemId, then create a new Item and re-add it.

I had a very similar issue and this is how I solved it… Hope someone will find it helpful

I had a table with a list of items shown in a table with a status Open|Closed . User could filter on all open items and close few of them. So when an open item is marked as closed, it would disappear from the table but I have update the table row as the user could reset the filter and that row need to show as closed.

What i did was to save the current state of the filter fields, (Since we add the filters, we know what filters are applied) remove all filters from the container, update the table, and then re-apply the filter from that saved state. Not sure if it is too much of an overhead. It worked fine for me and i dont see any major performance issues.

At least I didnt mess with a method which was not supposed to be overridden.

Hari