Bcx-aurelia-reorderable-repeat and value converter

I’m using the reorderable-repeat (with great success).

I am trying to use a simple filter valueConverter to filter the results, but I’m getting warned

Inner Error:
Message: ValueConverter is not supported in reorderable-repeat

Is there any way to apply a filter to the list?

The filter is nothing more than

export class MachinesFilterValueConverter {
  public toView(list: IMachineListItem[], search: string) {
    if (!search) {
      return list;
    }

    return list.filter(c => c.name.toLowerCase().includes(search.toLowerCase()));
  }
}
1 Like

You want to apply custom sorting to a filtered list, which is basically a snapshot, where the backing data can change at any time, this isn’t a straightforward thing to do in any framework that I know of, because you don’t have a real reference to the list you want to reorder.

I never used reorderable-repeat, but I’m guessing the plugin modifies the underlying array order as well, therefore you will need to bind to a ‘static’ array reference in order for this to work like you want.
You could achieve this by listening to changes on your original array, using a Collection Observer, and executing your filter when the list changes, populating a new list containing only the filtered values, and using reorderable-repeat on that list.
If you want to persist the custom ordering of the items when your source array changes, you should also write some logic that applies the custom sorting to the newly filtered list.

A lot of work IMO, might be worth reevaluating this requirement :slight_smile:

Perhaps you could hack something together by not really filtering the list but hiding the elements you don’t want to see instead, then you could in theory just bind to your source array. You can’t use if though, so performance might be an issue

1 Like

Thanks for your thoughts. I hadn’t really thought it through that well…

I’m going with

Blockquote
A lot of work IMO, might be worth reevaluating this requirement :slight_smile:

1 Like

You have to ask yourself what’s the expected result of reordering a filtered subarray of an array? I am not sure what exactly you want here.

reorderable-repeat mutates an array, that’s why it needs the original array.

1 Like

BTW @arnederuwe you can try reorderable-repeat here https://buttonwoodcx.github.io/doc-bcx-aurelia-dnd/#/reorderable-repeat

2 Likes

I use reorderable-repeat in it’s absolutely simplest form for a single list which the user is able to manually re-order.

On reorderable-after-reordering it calls

  protected orderChanged() {
    const sectorAreaIds = this.model.sectorAreaDetails.map(c => c.id);
    this.model.sectorAreaIds = sectorAreaIds;
  }

or

this.model.sectorAreaDetails.forEach((c,idx)=>{
   c.sortOrder = idx;
}

The original list is then saved back to the server with the new sortOrders.

The filtered view does not mutate the original list - it just provides a filtered view of the list

  public toView(list: IMachineListItem[], search: string) {
    if (!search) {
      return list;
    }

    return list.filter(c => c.name.toLowerCase().includes(search.toLowerCase()));
  }

In practice, I have many lists with say 20-30 items which have a sort order which can only be defined by the user. The user can sort the list into the desired order, and then select the required item. To make his life easier he should be able to quickly filter his list to find what he’s looking for

In this list the user needs to sort by Machine Group in the order as shown in the list. As you can see other than setting a manual sortOrder, I cannot use alphabetical or numeric sorting. The list reflects the movement of products as they flow through a production process. (This particular list will end up growing to some 300 items).

As the list grows, the user should be able to filter by any text on the page, i.e. by sector, sector area or machine group.

I hope this explains my use case.

1 Like

Alternatively use a normal repeater and a sort value converter along with your filter value converter.

I use something like:

export class SortValueConverter {
  toView(array, config = {propertyName: 'order', direction: 'ascending', asFloat: false}) {
    let factor = config.direction === 'ascending' ? 1 : -1;
    if (Array.isArray(array)) {
      return array.sort((a, b) => {
        if (config.asFloat) {
          return (parseFloat(a[config.propertyName]) - parseFloat(b[config.propertyName])) * factor;
        } else {
        return (a[config.propertyName] - b[config.propertyName]) * factor;
        }
      });
    }
  }
}

R

4 Likes

If I understand you correctly, @robertb’s suggestion is correct way to go.

When filter is off, it’s a reorderable-repeat on original list.
When filter is on, it’s a normal repeat on filtered list, without the drag-and-drop UI feature. Remember to remove the UI handler (your bars icon) for drag-and-drop, so that you would not mislead user to reorder the filtered list.

2 Likes

I hadn’t thought of doing that!

Many thanks

2 Likes